/* ** MJOIN -- Join overlapped or abutted notes ** psl 2/87 */ #include #include #define MAXCHAN 16 #define MAXKEY 128 main(argc, argv) char *argv[]; { if (argc != 1) { fprintf(stderr, "Usage: %s new\n", argv[0]); exit(2); } join(stdin, stdout); } join(ifp, ofp) FILE *ifp, *ofp; { register int i, k, v, curmode, chan; int key[MAXCHAN][MAXKEY]; long pko[MAXCHAN][MAXKEY]; /* pending key off */ long now, last; for (chan = MAXCHAN; --chan >= 0; ) for (k = MAXKEY; --k >= 0; ) key[chan][k] = pko[chan][k] = 0; curmode = 0; now = last = 0; while ((i = getc(ifp)) != EOF) { if (i == 0xF8) { now += MPU_CLOCK_PERIOD; continue; } now += i; for (chan = MAXCHAN; --chan >= 0; ) { for (k = MAXKEY; --k >= 0; ) { if (pko[chan][k] && pko[chan][k] < now) { put4(ofp, pko[chan][k] - last, 0x90 | chan, k, 0); last = pko[chan][k]; pko[chan][k] = 0; key[chan][k] = 0; } } } if ((k = getc(ifp)) == EOF) { fprintf(stderr, "EOF after 0x%x (now=%d)\n", i, now); exit(1); } if (k & 0x80) { if ((k & 0xF0) == 0xF0) { if (k < 0xF8) { /* sys excl or sys common */ if (k == 0xF0) { /* sys excl */ put2(ofp, now - last, k); do { k = getc(ifp); putc(k, ofp); } while (k != 0xF7); } else if (k == 0xF2) { /* song position */ k = getc(ifp); put4(ofp, now - last, 0xF2, k, getc(ifp)); } else if (k == 0xF3) { /* song select */ put3(ofp, now - last, k, getc(ifp)); } else { put2(ofp, now - last, k); } curmode = 0; } else /* sys real time */ put2(ofp, now - last, k); last = now; continue; } curmode = k; if ((k = getc(ifp)) == EOF) { fprintf(stderr, "EOF after %x (mode)\n", curmode); exit(1); } } i = curmode & 0xF0; chan = curmode % MAXCHAN; if (i == 0xA0 /* poly pressure */ || i == 0xB0 /* mod wheel */ || i == 0xE0) { /* pitch bend */ put4(ofp, now - last, curmode, k, getc(ifp)); last = now; continue; } else if (i == 0xC0 /* prog change */ || i == 0xD0) { /* chan pressure */ put3(ofp, now - last, curmode, k); last = now; continue; } else if (i == 0x90 || i == 0x80) { /* key-on/off event */ if ((v = getc(ifp)) == EOF) { fprintf(stderr, "unexpected EOF in mode %x\n", curmode); exit(1); } if (i == 0x80) /* hack to turn 0x80 into 0x90 */ v = 0; if (v != 0) { /* key-on */ if (key[chan][k] == 0 || join == 0) { put4(ofp, now - last, curmode, k, v); last = now; } key[chan][k]++; if (pko[chan][k]) { pko[chan][k] = 0; --key[chan][k]; } } else { /* key-off */ if (--key[chan][k] < 0) { /* extra key-off */ key[chan][k] = 0; continue; } if (key[chan][k] == 0 || join == 0) { pko[chan][k] = now; key[chan][k]++; } } } } for (chan = MAXCHAN; --chan >= 0; ) { for (k = MAXKEY; --k >= 0; ) { if (pko[chan][k]) { put4(ofp, pko[chan][k] - last, 0x90 | chan, k, 0); last = pko[chan][k]; } } } } put2(ofp, dt, mode) FILE *ofp; long dt; { if (ofp == (FILE *) 0) return; if (dt < 0) dt = 0; putdt(ofp, dt); putc(mode, ofp); } put3(ofp, dt, mode, n) FILE *ofp; long dt; { if (ofp == (FILE *) 0) return; if (dt < 0) dt = 0; putdt(ofp, dt); putc(mode, ofp); putc(n, ofp); } put4(ofp, dt, mode, k, v) FILE *ofp; long dt; { if (ofp == (FILE *) 0) return; if (dt < 0) dt = 0; putdt(ofp, dt); putc(mode, ofp); putc(k, ofp); putc(v, ofp); } putdt(ofp, dt) FILE *ofp; long dt; { while (dt >= MPU_CLOCK_PERIOD) { putc(RT_TCIP, ofp); dt -= MPU_CLOCK_PERIOD; } putc((char) dt, ofp); }