/* ** VMOD -- Modify velocity of an MPU data stream ** psl 8/88 */ #include #include #define BARLEN (2 * MPU_CLOCK_PERIOD) #define MAXT 64 #define DI 0 #define TI 1 struct tstr { double ratio; /* velocity ratio at end */ long beg; /* when the change begins */ long end; /* when the change ends */ } T[MAXT] = { 1., 0, 0, }; int Nt = 1; /* how many entries in T[] */ double interp(); extern double atof(); main(argc, argv) char *argv[]; { char *cp; int i, n; double q; FILE *ifp; if (argc < 2) { syntax: fprintf(stderr, "Usage: %s VSPEC [...] [files or stdin] >new\n", argv[0]); fprintf(stderr, "The VSPECs are in the form:\n"); fprintf(stderr, " -v#:##:###\n"); fprintf(stderr, "\t# is the (final) velocity ratio.\n"); fprintf(stderr, "\t## is the transition beginning point.\n"); fprintf(stderr, "\t### is the length of the transition.\n"); fprintf(stderr, "Both beginning and length are in units of input"); fprintf(stderr, " bars (480 MPU clocks) starting at 0.\n"); fprintf(stderr, "e.g. -v0.5:12:2 will cut the key velocity"); fprintf(stderr, " in half between input bars 12 & 14.\n"); exit(2); } for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'v': cp = &argv[i][2]; if ((q = atof(cp)) < 0.) goto syntax; T[Nt].ratio = q; for (; *cp && *cp != ':'; cp++); if (*cp++ != ':') goto syntax; T[Nt].beg = BARLEN * atof(cp); for (; *cp && *cp != ':'; cp++); if (*cp++ != ':') goto syntax; T[Nt].end = T[Nt].beg + BARLEN * atof(cp); if (T[Nt].end < T[Nt].beg) goto syntax; Nt++; break; default: goto syntax; } } } /****for (i = 0; i < Nt; i++) /**** fprintf(stderr, "%g\t%d\t%d\n", T[i].ratio, T[i].beg, T[i].end); /****/ n = 0; for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { if (ifp = fopen(argv[i], "r")) { vmod(ifp, stdout); fclose(ifp); n++; } else { perror(argv[i]); goto syntax; } } } if (n == 0) vmod(stdin, stdout); exit(0); } vmod(ifp, ofp) FILE *ifp, *ofp; { long now; MCMD *mp; now = 0L; putmcmd(0, 0); while (mp = getmcmd(ifp, now)) { now = mp->when; if ((mp->cmd[0] & M_CMD_MASK) == CH_KEY_ON) mp->cmd[2] = velcalc(now, mp->cmd[2]); putmcmd(ofp, mp); } } velcalc(now, vel) { int i; long dt, dur; double r, or, nr; if (vel == 0) return(0); for (i = 1; i < Nt && now > T[i].beg; i++) { or = T[i - 1].ratio; /* starting ratio */ nr = T[i].ratio; /* final ratio */ if (now >= T[i].end) r = nr; else { dur = T[i].end - T[i].beg; /* duration of change */ dt = now - T[i].beg; /* how far into change */ r = or + ((nr - or) * dt) / dur; } } vel = r * vel + 0.5; return(vel < 1? 1 : (vel > 127? 127 : vel)); }