/* ** STATS -- Print various statistics about an MPU piece ** psl 4/88 */ #include #include #define NUMCHAN MIDI_MAX_CHANS #define NUMKEYS 128 #define NUMVELS 128 #define MAXDUR 480 char Cstr[256], Istr[256]; int Strlim = 64; int Coflo = 0; int Ioflo = 0; int Events[NUMCHAN]; int Dur[MAXDUR]; int Mcmd[NUMCHAN][7]; int Key[NUMKEYS]; int Koff = 0; int Vel[NUMVELS]; int Sys[16]; int Chan = -1; /* specified channel */ int Vflg = 0; /* verbose */ char *key2name(), *endof(); main(argc, argv) char *argv[]; { register int i, j; FILE *ifp; j = 0; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'c': /* only count one channel */ Chan = atoi(&argv[i][2]) - 1; if (Chan < 0 || Chan >= NUMCHAN) goto syntax; break; case 'v': /* verbose */ Vflg++; Strlim = 240; break; default: syntax: fprintf(stderr, "Usage: %s [-c#] [-v] [files or stdin]\n", argv[0]); fprintf(stderr, "channel numbers are 1-16\n"); exit(2); } } else { if (ifp = fopen(argv[i], "r")) { printf("\n%s\t", argv[i]); stats(ifp); fclose(ifp); } else perror(argv[i]); j++; } } if (j == 0) stats(stdin); } stats(ifp) FILE *ifp; { register int i, j, chan, stat; char *cp; long now, start[NUMCHAN][NUMKEYS]; MCMD *mp; for (i = NUMCHAN; --i >= 0; Events[i] = 0) for (j = 7; --j >= 0; Mcmd[i][j] = 0); for (i = NUMKEYS; --i >= 0; Key[i] = 0); for (i = NUMVELS; --i >= 0; Vel[i] = 0); for (i = 16; --i >= 0; Sys[i] = 0); Coflo = Ioflo = 0; if (Vflg) { for (i = MAXDUR; --i >= 0; Dur[i] = 0); Koff = 0; for (i = NUMCHAN; --i >= 0; ) for (j = NUMKEYS; --j >= 0; start[i][j] = 0); } for (now = 0L; mp = getmcmd(ifp, now); now = mp->when) { stat = mp->cmd[0]; if (stat >= SX_CMD) { /* these have no channel */ if (Chan > -1) continue; Sys[stat & 0x0F]++; if (stat == SX_CMD && mp->cmd[1] == ID_MISC && SUBID(mp->cmd[2],mp->cmd[3]) == SUBID_HEADER) { mp->cmd[mp->len - 1] = '\0'; printf("%s\n", &mp->cmd[4]); } continue; } chan = (stat & M_CHAN_MASK); if (Chan > -1 && chan != Chan) continue; Events[chan]++; Mcmd[chan][(stat >> 4) & 0x07]++; if ((stat & M_CMD_MASK) == CH_KEY_OFF) { if (Vflg) Koff++; stat ^= (CH_KEY_OFF ^ CH_KEY_ON); mp->cmd[2] = 0; } if ((stat & M_CMD_MASK) == CH_KEY_ON && mp->cmd[2] > 0) { Key[mp->cmd[1]]++; Vel[mp->cmd[2]]++; if (Vflg) start[chan][mp->cmd[1]] = mp->when; } else if ((stat & M_CMD_MASK) == CH_KEY_ON) { /* (key-off) */ if (Vflg) { j = mp->when - start[chan][mp->cmd[1]]; Dur[j < MAXDUR? j : MAXDUR - 1]++; } } else if ((stat & M_CMD_MASK) == CH_PRG) { if ((cp = endof(Istr)) < Istr + Strlim) sprintf(cp, " %d=%d", chan + 1, mp->cmd[1] + 1); else Ioflo++; } else if ((stat & M_CMD_MASK) == CH_CTL) { if ((cp = endof(Cstr)) < Cstr + Strlim) sprintf(cp, " %d,%d=%d", chan + 1, mp->cmd[1], mp->cmd[2]); else Coflo++; } } printf("%g bars (%d MPU clocks)\n", now / (2. * MPU_CLOCK_PERIOD), now); for (chan = 0; chan < NUMCHAN; chan++) { if (Events[chan]) { if (Vflg) printf("%d event%s from chan %d\n", Events[chan], Events[chan] == 1? "" : "s", chan + 1); else printf("%sC%d: %d event%s", chan < 9? " " : "", chan + 1, Events[chan], Events[chan] == 1? "" : "s"); pmc(Mcmd[chan][0], "note-off", 0x80); pmc(Mcmd[chan][1], "note-on", 0x90); pmc(Mcmd[chan][2], "poly pressure", 0xA0); pmc(Mcmd[chan][3], "controller", 0xB0); pmc(Mcmd[chan][4], "program", 0xC0); pmc(Mcmd[chan][5], "channel pressure", 0xD0); pmc(Mcmd[chan][6], "pitch bend", 0xE0); if (!Vflg) printf("\n"); } } printf("Keys:"); i = 0; for (j = 0; j < NUMKEYS; j++) if (Key[j]) printf("%s%4d %3s(%x)", (i++ && (i % 4) == 1)? "\n\t" : "\t", Key[j], key2name(j), j); printf("\nVels:"); i = 0; for (j = 0; j < NUMVELS; j++) if (Vel[j]) printf("%s%4d %3d", (i++ && (i % 4) == 1)? "\n\t" : "\t", Vel[j], j); if (Vflg) { printf("\nDurs:"); i = 0; for (j = 0; j < MAXDUR; j++) if (Dur[j]) printf("%s%4d %3d", (i++ && (i % 4) == 1)? "\n\t" : "\t", Dur[j], j); } printf("\n"); if (i = Sys[0]) printf("%d sys exclusive (0xF0) command%s\n", i, i == 1? "" : "s"); if (i = Sys[1]) printf("%d sys undef (0xF1) command%s\n", i, i == 1? "" : "s"); if (i = Sys[2]) printf("%d measure select (0xF2) command%s\n", i, i == 1? "" : "s"); if (i = Sys[3]) printf("%d song select (0xF3) command%s\n", i, i == 1? "" : "s"); if (i = Sys[4]) printf("%d common undef (0xF4) command%s\n", i, i == 1? "" : "s"); if (i = Sys[5]) printf("%d common undef (0xF5) command%s\n", i, i == 1? "" : "s"); if (i = Sys[6]) printf("%d tune request (0xF6) command%s\n", i, i == 1? "" : "s"); if (i = Sys[8]) printf("%d no-op (0xF8) command%s\n", i, i == 1? "" : "s"); if (i = Sys[9]) printf("%d measure end (0xF9) command%s\n", i, i == 1? "" : "s"); if (i = Sys[10]) printf("%d RT start (0xFA) command%s\n", i, i == 1? "" : "s"); if (i = Sys[11]) printf("%d RT continue (0xFB) command%s\n", i, i == 1? "" : "s"); if (i = Sys[12]) printf("%d RT undef (0xFC) command%s\n", i, i == 1? "" : "s"); if (i = Sys[13]) printf("%d RT undef (0xFD) command%s\n", i, i == 1? "" : "s"); if (i = Sys[14]) printf("%d RT undef (0xFE) command%s\n", i, i == 1? "" : "s"); if (i = Sys[15]) printf("%d RT reset (0xFF) command%s\n", i, i == 1? "" : "s"); if (*Istr) printf("inst%s%s\n", Istr, Ioflo? "..." : ""); if (*Cstr) printf("cntl%s%s\n", Cstr, Coflo? "..." : ""); if (Vflg) printf("%d key-off (0x8?) command%s\n", Koff, Koff == 1? "" : "s"); } pmc(i, nam, num) char *nam; { if (i == 0) return; if (Vflg) printf("%d %s (0x%x) command%s\n", i, nam, num, i == 1? "" : "s"); else printf(" %d(0x%x)", i, num); } char * endof(str) register char *str; { for (; *str; str++); return(str); }