/*
**	DACK - Check .da files for time sequence, note on/off, & misc.
**	psl 9/85
*/
#include	<stdio.h>

#define	MAXCHAN	16
#define	MAXNOTE	128

char	*nnames[]	= {
	"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
};
char	*nn();
int	verbose	= 0;
extern	double	atof();

main(argc, argv)
char	*argv[];
{
	register int i, n;
	FILE *fp;

	n = 0;
	for (i = 1; i < argc; i++) {
	    if (argv[i][0] != '-') {
		n++;
		continue;
	    }
	    switch (argv[i][1]) {
	    case 'v':
		verbose++;
		break;
	    default:
		fprintf(stderr, "Usage: %s [-v] [files or stdin]\n", argv[0]);
		exit(2);
	    }
	}
	if (n == 0)
	    dack(stdin, "");
	else {
	    for (i = 1; i < argc; i++) {
		if (argv[i][0] == '-')
		    continue;
		if ((fp = fopen(argv[i], "r")) == NULL) {
		    perror(argv[i]);
		    continue;
		}
		dack(fp, n > 1? argv[i] : "");
		fclose(fp);
	    }
	}
}

dack(fp, file)
FILE	*fp;
char	*file;
{
	register int line, note, chan, active, maxact;
	char buf[128];
	int key[MAXCHAN][MAXNOTE], kl[MAXCHAN][MAXNOTE];
	double time, lastime;

	active = maxact = 0;
	lastime = 0.;
	for (note = MAXNOTE; --note >= 0; )
	    for (chan = MAXCHAN; --chan >= 0; )
		key[chan][note] = 0;
	for (line = 1; fgets(buf, sizeof buf, fp) != NULL; line++) {
	    if (buf[0] == '\n')
		continue;
	    time = atof(&buf[13]);
	    if (time < lastime)
		printf("%s time %g follows %g (line %d)\n",
		 file, time, lastime, line);
	    lastime = time;
	    if (buf[3] == '9')
		chan = hex(buf[4]);
	    if (buf[30] == 'k' && buf[31] == 'o') {
		if (buf[32] == 'n') {
		    note = hex(buf[6]) * 16 + hex(buf[7]);
		    if (key[chan][note] & verbose)
			printf("%s multiple key-on %s 0x%x (line %d)\n",
			 file, nn(note), note, line);
		    else {
			if (active++ >= 16)
			    printf("%s %d voices used (line %d)\n",
			     file, active, line);
			if (active > maxact)
			    maxact = active;
		    }
		    key[chan][note]++;
		    kl[chan][note] = line;
		} else if (buf[32] == 'f') {
		    note = hex(buf[6]) * 16 + hex(buf[7]);
		    if (key[chan][note] == 0)
			printf("%s extra key-off %s 0x%x (line %d)\n",
			 file, nn(note), note, line);
		    else {
			--key[chan][note];
			--active;
		    }
		} else
		    printf("%s Weird code - ko%c%c (line %d)\n",
		     file, buf[32], buf[33], line);
	    }
	}
	for (note = MAXNOTE; --note >= 0; )
	    for (chan = MAXCHAN; --chan >= 0; )
		if (key[chan][note])
		    printf("%s key %s 0x%x left on since line %d\n",
		     file, nn(note), note, kl[chan][note]);
	if (verbose)
	    printf("%s Max simultaneous notes = %d\n", file, maxact);
}

char	*
nn(note)
{
	register char *bp, *cp, oct;
	static char buf[5];

	for (bp = buf, cp = nnames[note%12]; *bp = *cp++; bp++);
	oct = note / 12 - 1;
	if (oct < 0) {
	    *bp++ = '-';
	    oct = -oct;
	}
	*bp++ = '0' + oct;
	*bp++ = '\0';
	return(buf);
}


hex(c)
{
	if (c >= '0' && c <= '9')
	    return(c - '0');
	if (c >= 'a' && c <= 'f')
	    return(10 + c - 'a');
	if (c >= 'A' && c <= 'F')
	    return(10 + c - 'A');
	return(0);
}
