/* ** GC2MPU -- Convert "gc" format files to "mpu" files ** psl 5/88 */ #include #include #define P_BLOCK 0 #define P_SPLIT 1 #define P_SPLIT3 2 #define P_ALT 3 #define MAXART 16 #define MAXVEL 16 #define MAXEV 256 #define REST -1 #define NEVER 0x7FFFFFFF; #define MAXF 16 int Nmult = 1; /* #MULT value */ int Cpl; /* MPU clocks per line of input */ int Pick; /* picking pattern */ int Artic[MAXART]; /* articulation array (in Aunits) */ int Aunits = 1000; /* denominator for Artic[] */ int Nartic; /* number of entries in Artic[] */ int Cartic = 0; /* current index into Artic[] */ int Vel[MAXVEL] = { 64 }; /* key velocity array */ int Nvel = 1; /* number of entries in Vel[] */ int Cvel = 0; /* current index into Vel[] */ long T = 0; /* cumulative time */ int Cbs; /* clocks between strings in strum */ int Nr; /* input line number */ int Nn[] = { 9, 11, 0, 2, 4, 5, 7, }; double Beats = 4.; /* input lines per bar */ double Tempo = 100.; /* arbitrarily, 100. = normal */ struct pickstr { char *name; int pick; } Picks[] = { { "block", P_BLOCK, }, { "split", P_SPLIT, }, { "split3", P_SPLIT3, }, { "alt", P_ALT, }, 0, }; #define DEFSTYLE "bum-chang" struct stylestr { char *name; int pick; int cbs; int nartic; int artic[MAXART]; int nvel; int vel[MAXART]; } Styles[] = { { "bum-chang", P_SPLIT, 3, 1, { 1000, }, 1, { 64, }, }, { "swing", P_BLOCK, 0, 2, { 667, 250, }, 1, { 64, }, }, { "waltz", P_SPLIT3, 3, 3, { 1000, 500, 500, }, 1, { 64, }, }, 0, }; extern double atof(); main(argc, argv) char *argv[]; { int i; FILE *ifp; ifp = stdin; Cpl = cplcalc(Tempo, Beats); /* set default clocks/line */ style(DEFSTYLE); /* set default style */ for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { default: goto syntax; } } else if (!(ifp = fopen(argv[i], "r"))) { perror(argv[i]); syntax: fprintf(stderr, "Usage: %s [files or stdin]\n", argv[0]); exit(2); } else gc2mpu(ifp); } if (ifp == stdin) gc2mpu(ifp); exit(0); } gc2mpu(ifp) FILE *ifp; { char buf[512], a[MAXF][128]; u_char mbuf[8]; int i, j, nf, nt, nev, note[MAXEV], kvel[MAXEV]; int kv1, kv2, kv3, kv4; long bt1, et1, bt2, et2, bt3, et3, bt4, et4, tmin, when[MAXEV]; MCMD m; m.cmd = mbuf; for (Nr = 1; fgets(buf, sizeof buf, ifp) != NULL; Nr++) { nf = sscanf(buf, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15]); if (nf <= 0) continue; if (a[0][0] == '#') { if (strcmp(a[0], "#") == 0) continue; if (strcmp(a[0], "#ARTIC") == 0 || strcmp(a[0], "#ARTICULATION") == 0) { for (i = 1; i < nf; i++) Artic[i - 1] = 1000. * atof(a[i]); Nartic = nf - 1; Cartic = 0; } else if (strcmp(a[0], "#SPEED") == 0) { Beats = atof(a[1]); Cpl = cplcalc(Tempo, Beats); Cartic = Cvel = 0; } else if (strcmp(a[0], "#MULT") == 0 || strcmp(a[0], "#MULTIPLICITY") == 0) { Nmult = atoi(a[1]); Cartic = Cvel = 0; } else if (strcmp(a[0], "#PICK") == 0) { for (i=0; Picks[i].name && strcmp(a[1],Picks[i].name); i++); if (!Picks[i].name) { fprintf(stderr, "Unrecognized pick pat: %s\n", a[1]); fprintf(stderr, "Known patterns are:"); for (i = 0; Picks[i].name; i++) fprintf(stderr, " %s", Picks[i].name); fprintf(stderr, "\n"); exit(1); } Pick = Picks[i].pick; Cartic = Cvel = 0; } else if (strcmp(a[0], "#STRUM") == 0) { Cbs = MPU_CLOCK_PERIOD * atof(a[1]) / 2.; } else if (strcmp(a[0], "#STYLE") == 0) { Cartic = Cvel = 0; style(a[1]); } else if (strcmp(a[0], "#TEMPO") == 0) { Tempo = atoi(a[1]); Cpl = cplcalc(Tempo, Beats); } else if (strcmp(a[0], "#VOL") == 0 || strcmp(a[0], "#VOLUME") == 0 || strcmp(a[0], "#VEL") == 0 || strcmp(a[0], "#VELOCITY") == 0) { for (i = 1; i < nf; i++) Vel[i - 1] = atoi(a[i]); Nvel = nf - 1; Cvel = 0; } continue; } for (nt = 0; nt < Nmult; nt++) { nev = 0; if (Pick == P_BLOCK) { bt1 = T; et1 = bt1 + (Artic[Cartic] * Cpl) / Aunits; Cartic = (Cartic + 1) % Nartic; kv1 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; for (i = 0; i < nf; i++) { when[nev] = bt1; note[nev] = knum(a[i]); kvel[nev++] = kv1; when[nev] = et1; note[nev] = note[nev - 1]; kvel[nev++] = 0; } } else if (Pick == P_SPLIT) { bt1 = T; et1 = bt1 + (Artic[Cartic] * Cpl) / (2 * Aunits); Cartic = (Cartic + 1) % Nartic; kv1 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; bt2 = T + Cpl / 2; et2 = bt2 + (Artic[Cartic] * Cpl) / (2 * Aunits); Cartic = (Cartic + 1) % Nartic; kv2 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; when[nev] = bt1; note[nev] = knum(a[0]); kvel[nev++] = kv1; when[nev] = et1; note[nev] = note[nev - 1]; kvel[nev++] = 0; for (i = 1; i < nf; i++) { when[nev] = bt2 + (i - nf + 1) * Cbs; note[nev] = knum(a[i]); kvel[nev++] = kv2; when[nev] = et2; note[nev] = note[nev - 1]; kvel[nev++] = 0; } } else if (Pick == P_SPLIT3) { bt1 = T; et1 = bt1 + (Artic[Cartic] * Cpl) / (3 * Aunits); Cartic = (Cartic + 1) % Nartic; kv1 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; bt2 = T + Cpl / 3; et2 = bt2 + (Artic[Cartic] * Cpl) / (3 * Aunits); Cartic = (Cartic + 1) % Nartic; kv2 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; bt3 = T + (Cpl * 2) / 3; et3 = bt3 + (Artic[Cartic] * Cpl) / (3 * Aunits); Cartic = (Cartic + 1) % Nartic; kv3 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; when[nev] = bt1; note[nev] = knum(a[0]); kvel[nev++] = kv1; when[nev] = et1; note[nev] = note[nev - 1]; kvel[nev++] = 0; for (i = 1; i < nf; i++) { when[nev] = bt2 + (i - nf + 1) * Cbs; note[nev] = knum(a[i]); kvel[nev++] = kv2; when[nev] = et2; note[nev] = note[nev - 1]; kvel[nev++] = 0; when[nev] = bt3 + (i - nf + 1) * Cbs; note[nev] = note[nev - 1]; kvel[nev++] = kv3; when[nev] = et3; note[nev] = note[nev - 1]; kvel[nev++] = 0; } } else if (Pick == P_ALT) { bt1 = T; et1 = bt1 + (Artic[Cartic] * Cpl) / (4 * Aunits); Cartic = (Cartic + 1) % Nartic; kv1 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; bt2 = T + (Cpl * 1) / 4; et2 = bt2 + (Artic[Cartic] * Cpl) / (4 * Aunits); Cartic = (Cartic + 1) % Nartic; kv2 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; bt3 = T + (Cpl * 2) / 4; et3 = bt3 + (Artic[Cartic] * Cpl) / (4 * Aunits); Cartic = (Cartic + 1) % Nartic; kv3 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; bt4 = T + (Cpl * 3) / 4; et4 = bt4 + (Artic[Cartic] * Cpl) / (4 * Aunits); Cartic = (Cartic + 1) % Nartic; kv4 = Vel[Cvel]; Cvel = (Cvel + 1) % Nvel; when[nev] = bt1; note[nev] = knum(a[0]); kvel[nev++] = kv1; when[nev] = et1; note[nev] = note[nev - 1]; kvel[nev++] = 0; when[nev] = bt3; note[nev] = knum(a[1]); kvel[nev++] = kv3; when[nev] = et3; note[nev] = note[nev - 1]; kvel[nev++] = 0; for (i = 2; i < nf; i++) { when[nev] = bt2 + (i - nf + 1) * Cbs; note[nev] = knum(a[i]); kvel[nev++] = kv2; when[nev] = et2; note[nev] = note[nev - 1]; kvel[nev++] = 0; when[nev] = bt4 + (i - nf + 1) * Cbs; note[nev] = note[nev - 1]; kvel[nev++] = kv4; when[nev] = et4; note[nev] = note[nev - 1]; kvel[nev++] = 0; } } T += Cpl; for (i = 0; i < nev; i++) if (note[i] == REST) when[i] = NEVER; m.len = 3; for (;;) { tmin = NEVER; j = -1; for (i = 0; i < nev; i++) if (when[i] < tmin) tmin = when[j = i]; if (j == -1) break; if (tmin > T) tmin = T; m.when = tmin; mbuf[0] = CH_KEY_ON; mbuf[1] = note[j]; mbuf[2] = kvel[j]; putmcmd(stdout, &m); when[j] = NEVER; } } m.when = T; m.len = 1; mbuf[0] = RT_TCWME; putmcmd(stdout, &m); } } cplcalc(t, b) double t, b; { return((int) ((100 * 2 * MPU_CLOCK_PERIOD) / (t * b) + 0.5)); } style(cp) char *cp; { int i, j; for (i = 0; Styles[i].name && strcmp(cp, Styles[i].name); i++); if (!Styles[i].name) { fprintf(stderr, "Unrecognized style: %s\n", cp); fprintf(stderr, "Known styles are:"); for (i = 0; Styles[i].name; i++) fprintf(stderr, " %s", Styles[i].name); fprintf(stderr, "\n"); exit(1); } Pick = Styles[i].pick; Nartic = Styles[i].nartic; for (j = Nartic; --j >= 0; Artic[j] = Styles[i].artic[j]); Nvel = Styles[i].nvel; for (j = Nvel; --j >= 0; Vel[j] = Styles[i].vel[j]); Cbs = Styles[i].cbs; } knum(code) char *code; { register char *cp; int note, oct; cp = code; if (*cp == '-' || *cp == 'R') return(REST); if (*cp < 'A' || 'G' < *cp) { fprintf(stderr, "Bad note format '%s' in line %d\n", code, Nr); exit(1); } note = Nn[*cp++ - 'A']; while (*cp == 'b' || *cp == '#') note += (*cp++ == 'b'? -1 : 1); oct = *cp - '0'; if (oct < -1 || oct > 9) { fprintf(stderr, "Octave out of range '%s' in line %d\n", code, Nr); exit(1); } return(12 + oct * 12 + note); }