/* ** MPU2PC -- Compute pitch change track from MPU data (e.g. for SPX90) ** psl 9/88 */ #include #include #define BIGTIME 0x7FFFFFFF #define MAXPC 16 #define MAXCHAN 16 #define MAXMIDILEN 4 /* longest non-sysex MIDI command */ struct pcstr { int out; /* channel for pitch change info */ int in; /* channel for pitch info */ int ref; /* channel for pitch reference info */ } Pc[MAXPC]; char Key[MAXCHAN]; /* current note, 0 => no note */ int Npc = 0; /* number of pitch change sets */ int Sysex = 0; int Bkey = 60; /* base key, C3 [?] default */ main(argc, argv) char *argv[]; { register int i, chan; char *cp; long now; MCMD *mp; for (i = 1; i < argc; i++) { if (argv[i][0] == '-') { switch (argv[i][1]) { case 'b': /* base key */ Bkey = name2key(&argv[i][2]); if (Bkey <= 0 || Bkey > 127) goto syntax; break; default: goto syntax; } } else { for (cp = argv[i]; *cp && *cp != '='; cp++); if (*cp++ != '=') goto syntax; if (Npc >= MAXPC) { fprintf(stderr, "Too many pitch change specs.\n"); goto syntax; } Pc[Npc].out = atoi(argv[i]) - 1; Pc[Npc].in = atoi(cp) - 1; for (; *cp && *cp != '-'; cp++); if (*cp++ != '-') goto syntax; Pc[Npc].ref = atoi(cp) - 1; if (Pc[Npc].out < 0 || Pc[Npc].out >= MAXCHAN || Pc[Npc].in < 0 || Pc[Npc].in >= MAXCHAN || Pc[Npc].ref < 0 || Pc[Npc].ref >= MAXCHAN) goto syntax; Npc++; } } if (Npc <= 0) { syntax: fprintf(stderr, "Usage: %s [-bKEY] o=i-r ... file2\n", argv[0]); fprintf(stderr, "KEY is the base key for pitch change info.\n"); fprintf(stderr, "default is -bC3\n"); fprintf(stderr, "o is the output channel for pitch change info.\n"); fprintf(stderr, "i is the input channel with pitch info.\n"); fprintf(stderr, "r is the input channel with reference pitch.\n"); fprintf(stderr, "All channels are in the range 1-16.\n"); exit(2); } putmcmd((FILE *) 0, (MCMD *) 0); for (now = 0L; mp = getmcmd(stdin, now); ) { now = mp->when; if ((mp->cmd[0] & M_CMD_MASK) == CH_KEY_ON) { chan = mp->cmd[0] & M_CHAN_MASK; Key[chan] = mp->cmd[2]? mp->cmd[1] : 0; for (i = 0; i < Npc; i++) if (Pc[i].in == chan || Pc[i].ref == chan) output(now, Pc[i].out, Key[Pc[i].in], Key[Pc[i].ref]); } } for (i = 0; i < Npc; i++) output(now + 1, Pc[i].out, 0, 0); /* force out buffered output */ exit(0); } static unsigned char Cmdbuf[MAXCHAN << 2]; static int Lastkey[MAXCHAN] = -1; static MCMD M[MAXCHAN]; output(now, chan, inkey, refkey) long now; { MCMD *mp; mp = &M[chan]; if (now > mp->when && mp->cmd[0] && mp->cmd[1] != Lastkey[chan]) { putmcmd(stdout, mp); Lastkey[chan] = mp->cmd[1]; } mp->when = now; mp->len = 3; mp->cmd = &Cmdbuf[chan << 2]; mp->cmd[0] = CH_KEY_ON | chan; mp->cmd[1] = Bkey + ((inkey && refkey)? inkey - refkey : 0); mp->cmd[2] = 1; }