#include #include #d MAX 30 #d FNULL (FILE *)0 static MpuCmd m[MAX]; static unsigned char mbuf[MAX][10]; static long time[MAX]; static int OpenFiles = 0; static int Period = MPU_CLOCK_PERIOD; static mintime(f,n) FILE *f[]; { long t = 9999; Int i; loop(i,n) if (f[i] && time[i] < t) t = time[i]; return t; } static Get(f,i) FILE *f[]; { if (GetMpuCmd(f[i],&m[i])) { strcpy(mbuf[i],m[i].mpu_cmd), m[i].mpu_cmd = mbuf[i]; if (m[i].time_tag == RT_TCIP) { time[i] += Period; return Get(f,i); } time[i] += m[i].mpu_time; if (*mbuf[i] == RT_TCWME) return Get(f,i); } else OpenFiles--, close(fileno(f[i])), f[i] = (FILE *)NULL; } static Put(f,i,nmin) FILE *f; { if (nmin) time[i] = 0; m[i].time_tag = (unsigned char)time[i]; m[i].mpu_time = time[i]; time[i] = 0; PutMpuCmd(f,&m[i]); } static deduct(n,t) { Int i; loop(i,n) time[i] -= t; } MidiMerge(f, n, out) FILE *f[]; /* array of input files */ int n; /* number of files in 'f' */ FILE *out; /* where to write output */ /* ** Read midi data from the 'n' files in 'f' and merge it ** in time order, writing the result on 'out'. ** Every '2*Period' ticks a counter ('cum', below) overflows ** telling us to output a timing clock with measure end. */ { Int i, t=0, cum = 0; OpenFiles = n; loop(i,n) Get(f,i); while (OpenFiles) { while ((t = mintime(f,n)) >= Period) { deduct(n,Period); cum += Period; PutTCIP(out); /* Timing clock in play */ if (cum >= 2*Period) PutTCWME(out,0), cum = 0; t = 0; } Again: cum += t; if (cum >= 2*Period) { /* put out TimingClockWithMeasureEnd */ cum = t - (cum - 2*Period); PutTCWME(out,cum); deduct(n,cum); t -= cum; if (t > 0) goto Again; cum = 0; } else { int nmin = 0; /* if true, there's > 1 min (simultaneous) */ loop(i,n) if (f[i] && time[i] == t) Put(out,i,nmin++), Get(f,i); else time[i] -= t; } } }