/* ** ADJUST -- Adjust note placements ** Timing marks are taken from specified channel. ** Two pass; on first observe timing marks & calculate timing changes. ** On second pass adjust all key-ons and key-offs. ** psl 1/86 */ #include #include #define MAXCHAN 16 #define MAXKEY 128 #define UNITY 1024 #define MAXQ 4096 long mark[MAXQ]; /* when the timing marks appeared */ int nmark = 0; char tempfile[64]; int cpm = MPU_CLOCK_PERIOD / 2; /* clocks per mark */ int tchan = -1; /* timing mark channel */ main(argc, argv) char *argv[]; { FILE *tfp; int comp(); if (argc < 2) { syntax: fprintf(stderr, "Usage: %s -c# [-q#] new\n", argv[0]); fprintf(stderr, "-c# sets the timing mark channel (1..16)\n"); fprintf(stderr, "-q# sets the number of timing marks per bar\n"); fprintf(stderr, "default is: -q4\n"); exit(2); } while (--argc > 0) { if (argv[argc][0] == '-') { switch (argv[argc][1]) { case 'c': tchan = atoi(&argv[argc][2]) - 1; break; case 'q': cpm = (2 * MPU_CLOCK_PERIOD) / atoi(&argv[argc][2]); break; default: goto syntax; } } } if (tchan < 0) goto syntax; sprintf(tempfile, "/tmp/adjust%d", getpid()); if ((tfp = fopen(tempfile, "w")) == (FILE *) NULL) { perror(tempfile); exit(1); } pass1(stdin, tfp); fclose(tfp); if ((tfp = fopen(tempfile, "r")) == (FILE *) NULL) { perror(tempfile); exit(1); } process(tfp, stdout); unlink(tempfile); } pass1(ifp, ofp) FILE *ifp, *ofp; { register int i, k, v, curmode, dur, chan; long now, last, start[MAXCHAN][MAXKEY]; mark[nmark++] = 0; /* first mark is at 0 */ curmode = 0; now = last = 0; while ((i = getc(ifp)) != EOF) { if (i == 0xF8) { now += MPU_CLOCK_PERIOD; continue; } now += i; 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); } put4(ofp, now - last, curmode, k, v); last = now; if (i == 0x90 && v != 0 && chan == tchan && now != 0) mark[nmark++] = now; } } mark[nmark] = 2 * mark[nmark - 1] - mark[nmark - 2]; /* in case */ } process(ifp, ofp) FILE *ifp, *ofp; { register int i, k, v, curmode, stat; long onow, nnow, last; long adjust(); curmode = 0; onow = last = 0; while ((i = getc(ifp)) != EOF) { if (i == RT_TCIP) { onow += MPU_CLOCK_PERIOD; continue; } onow += i; nnow = adjust(onow); curmode = getc(ifp); stat = curmode & 0xF0; if (curmode > 0xF3 || curmode == 0xF1) { put2(ofp, nnow - last, curmode); last = nnow; continue; } if (curmode == 0xF0) { /* sys excl */ put2(ofp, nnow - last, curmode); last = nnow; do { k = getc(ifp); putc(k, ofp); } while (k != 0xF7); continue; } k = getc(ifp); if (stat == 0xC0 || stat == 0xD0 || curmode == 0xF3) { put3(ofp, nnow - last, curmode, k); last = nnow; continue; } v = getc(ifp); put4(ofp, nnow - last, curmode, k, v); last = nnow; } if (curmode != RT_TCWME) /* a final command */ put2(ofp, nnow > last? nnow - last : 0, RT_TCWME); } long adjust(t) long t; { register int h, l, dt; for (h = 1; h < nmark && mark[h] < t; h++); l = h - 1; dt = (mark[h] - mark[l]); if (dt < 1) dt = 1; return(l * cpm + ((t - mark[l]) * cpm) / dt); } 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); }