/* ** TMOD -- Modify timing of a MPU data stream ** psl 5/88 */ #include #include #define BARLEN (2 * MPU_CLOCK_PERIOD) #define MAXT 64 #define DI 0 #define TI 1 struct tstr { int dort; /* duration or tempo interpolation */ double ratio; /* duration ratio at end */ long beg; /* when the change begins */ long end; /* when the change ends */ } T[MAXT] = { DI, 1., 0, 0, }; int Nt = 1; /* how many entries in T[] */ long whencalc(); 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 TSPEC [...] [files or stdin] >new\n", argv[0]); fprintf(stderr, "The TSPECs can be in one of two forms:\n"); fprintf(stderr, " -d#:##:###\n"); fprintf(stderr, "\t# is the (final) duration ratio.\n"); fprintf(stderr, "\t## is the transition beginning point.\n"); fprintf(stderr, "\t### is the length of the transition.\n"); fprintf(stderr, " -t#:#:#\n"); fprintf(stderr, "\t# is the ending tempo 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. either -d2:12:2 or -t0.5:12:2 will cut the"); fprintf(stderr, " tempo 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 'd': case 't': cp = &argv[i][2]; if ((q = atof(cp)) == 0.) goto syntax; if (argv[i][1] == 'd') T[Nt].dort = DI; else { T[Nt].dort = TI; q = 1. / q; } 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")) { tmod(ifp, stdout); fclose(ifp); n++; } else { perror(argv[i]); goto syntax; } } } if (n == 0) tmod(stdin, stdout); exit(0); } tmod(ifp, ofp) FILE *ifp, *ofp; { long now; MCMD *mp; now = 0L; putmcmd(0, 0); while (mp = getmcmd(ifp, now)) { now = mp->when; mp->when = whencalc(now); putmcmd(ofp, mp); } } long whencalc(now) long now; { int i; long when, dt, dur; double r, or, nr; when = 0L; for (i = 1; i < Nt && now > T[i].beg; i++) { or = T[i - 1].ratio; /* starting duration ratio */ nr = T[i].ratio; /* final duration ratio */ dt = T[i].beg - T[i - 1].end; /* time at previous ratio */ if (dt > 0L) when += or * dt; dur = T[i].end - T[i].beg; /* duration of change */ if (dur > 0L) { dt = (now < T[i].end)? (now - T[i].beg) : dur; r = interp(T[i].dort, or, nr, dur, dt); /* avg duration ratio */ when += r * dt; } } dt = now - T[i - 1].end; if (dt > 0L) when += T[i - 1].ratio * dt; return(when); } double interp(dort, b, e, whole, part) /* "linearly" interpolat between b & e */ double b, e; long whole, part; { double r; if (dort == TI) { b = 1. / b; e = 1. / e; } r = b + ((e - b) * part) / whole; return(dort == TI? 1. / r : r); }