/* * GLIB - a Generic LIBrarian and editor for synths * * MicroWave support, by Tim Thompson * * Function names and other things use the following prefix convention - * an 'm' (for MicroWave) followed by 2 characters: * * msp - Single Patches * mmp - Multi Patches * muw - User Waves (the waveforms) * mwt - Wave Tables (control tables) * * These values are also used as the suffixes on file names, e.g. * files containing single patches are called *.msp. * * On UNIX (or any system for which getenv() works), you can * set the TABLEOFFSET and WAVEOFFSET variables to get access to * the other sections of the tables and waves (the ROM ones). * However, you shouldn't have to do that, since I've already done * it and stored the results in the following files (which should be * in this directory or in the samples directory): * * mwave00_11.mwt The Wave Tables in ROM positions 0-11 * mwave12_23.mwt ditto ... * mwave16_27.mwt ditto ... * * mwave000_060.muw The Waves in ROM positions 0-60 * mwave061_121.muw ditto ... * mwave122_182.muw ditto ... * mwave183_243.muw * * You can also set the WAVEDEVICE variable to control the DeviceID. */ #include "glib.h" #include #define WAVEOFFSET 246 #define TABLEOFFSET 32 #define WAVESIZE 128 #define TABLESIZE 256 #define WAVEDEVICE 0 char *visnum(), *vissamp(); #ifdef unix char *getenv(); #endif /* This is the screen setup fo the User Wave editor */ struct labelinfo Lmuw[] = { 5,0,"h = left", 6,0,"l = right", 7,0,"k = up", 8,0,"j = down", 9,0,"K = incr", 10,0,"J = decr", 11,0,"q = quit", 13,0,"Pitch", 14,0,"Vol", 15,0,"Dur", 16,0,"Chan", 17,0,"=note", # line 22 "mwave.mnu" -1,-1,NULL }; struct paraminfo Pmuw[] = { /* NAME TYPE POS MAX OFFSET MASK SHIFT ADHOC */ "autopitch",NULL,-1,-1,13,6,visnum,0,127,60,0, "autovol",NULL,-1,-1,14,5,visnum,0,127,63,0, "autodur",NULL,-1,-1,15,6,visnum,1,20,5,0, "autochan",NULL,-1,-1,16,5,visnum,1,16,1,0, "sample1",NULL,-1,-1,18,13,vissamp,0,255,0,0, "sample2",NULL,-1,-1,18,14,vissamp,0,255,0,0, "sample3",NULL,-1,-1,18,15,vissamp,0,255,0,0, "sample4",NULL,-1,-1,18,16,vissamp,0,255,0,0, "sample5",NULL,-1,-1,18,17,vissamp,0,255,0,0, "sample6",NULL,-1,-1,18,18,vissamp,0,255,0,0, "sample7",NULL,-1,-1,18,19,vissamp,0,255,0,0, "sample8",NULL,-1,-1,18,20,vissamp,0,255,0,0, "sample9",NULL,-1,-1,18,21,vissamp,0,255,0,0, "sample10",NULL,-1,-1,18,22,vissamp,0,255,0,0, "sample11",NULL,-1,-1,18,23,vissamp,0,255,0,0, "sample12",NULL,-1,-1,18,24,vissamp,0,255,0,0, "sample13",NULL,-1,-1,18,25,vissamp,0,255,0,0, "sample14",NULL,-1,-1,18,26,vissamp,0,255,0,0, "sample15",NULL,-1,-1,18,27,vissamp,0,255,0,0, "sample16",NULL,-1,-1,18,28,vissamp,0,255,0,0, "sample17",NULL,-1,-1,18,29,vissamp,0,255,0,0, "sample18",NULL,-1,-1,18,30,vissamp,0,255,0,0, "sample19",NULL,-1,-1,18,31,vissamp,0,255,0,0, "sample20",NULL,-1,-1,18,32,vissamp,0,255,0,0, "sample21",NULL,-1,-1,18,33,vissamp,0,255,0,0, "sample22",NULL,-1,-1,18,34,vissamp,0,255,0,0, "sample23",NULL,-1,-1,18,35,vissamp,0,255,0,0, "sample24",NULL,-1,-1,18,36,vissamp,0,255,0,0, "sample25",NULL,-1,-1,18,37,vissamp,0,255,0,0, "sample26",NULL,-1,-1,18,38,vissamp,0,255,0,0, "sample27",NULL,-1,-1,18,39,vissamp,0,255,0,0, "sample28",NULL,-1,-1,18,40,vissamp,0,255,0,0, "sample29",NULL,-1,-1,18,41,vissamp,0,255,0,0, "sample30",NULL,-1,-1,18,42,vissamp,0,255,0,0, "sample31",NULL,-1,-1,18,43,vissamp,0,255,0,0, "sample32",NULL,-1,-1,18,44,vissamp,0,255,0,0, "sample33",NULL,-1,-1,18,45,vissamp,0,255,0,0, "sample34",NULL,-1,-1,18,46,vissamp,0,255,0,0, "sample35",NULL,-1,-1,18,47,vissamp,0,255,0,0, "sample36",NULL,-1,-1,18,48,vissamp,0,255,0,0, "sample37",NULL,-1,-1,18,49,vissamp,0,255,0,0, "sample38",NULL,-1,-1,18,50,vissamp,0,255,0,0, "sample39",NULL,-1,-1,18,51,vissamp,0,255,0,0, "sample40",NULL,-1,-1,18,52,vissamp,0,255,0,0, "sample41",NULL,-1,-1,18,53,vissamp,0,255,0,0, "sample42",NULL,-1,-1,18,54,vissamp,0,255,0,0, "sample43",NULL,-1,-1,18,55,vissamp,0,255,0,0, "sample44",NULL,-1,-1,18,56,vissamp,0,255,0,0, "sample45",NULL,-1,-1,18,57,vissamp,0,255,0,0, "sample46",NULL,-1,-1,18,58,vissamp,0,255,0,0, "sample47",NULL,-1,-1,18,59,vissamp,0,255,0,0, "sample48",NULL,-1,-1,18,60,vissamp,0,255,0,0, "sample49",NULL,-1,-1,18,61,vissamp,0,255,0,0, "sample50",NULL,-1,-1,18,62,vissamp,0,255,0,0, "sample51",NULL,-1,-1,18,63,vissamp,0,255,0,0, "sample52",NULL,-1,-1,18,64,vissamp,0,255,0,0, "sample53",NULL,-1,-1,18,65,vissamp,0,255,0,0, "sample54",NULL,-1,-1,18,66,vissamp,0,255,0,0, "sample55",NULL,-1,-1,18,67,vissamp,0,255,0,0, "sample56",NULL,-1,-1,18,68,vissamp,0,255,0,0, "sample57",NULL,-1,-1,18,69,vissamp,0,255,0,0, "sample58",NULL,-1,-1,18,70,vissamp,0,255,0,0, "sample59",NULL,-1,-1,18,71,vissamp,0,255,0,0, "sample60",NULL,-1,-1,18,72,vissamp,0,255,0,0, "sample61",NULL,-1,-1,18,73,vissamp,0,255,0,0, "sample62",NULL,-1,-1,18,74,vissamp,0,255,0,0, "sample63",NULL,-1,-1,18,75,vissamp,0,255,0,0, "sample64",NULL,-1,-1,18,76,vissamp,0,255,0,0, NULL,NULL,-1,-1,-1,-1,visnum,0,0,0,0 }; #define SOUNDSIZE 180 #define MULTISIZE 226 char * mwvnum(n) { static char v[3]; if ( n < 32 ) sprintf(v,"A%02d",n+1); else sprintf(v,"B%02d",n+1-32); return(v); } int mwchecksum(p,n) char *p; int n; { int sum = 0; while ( n-- > 0 ) { sum += *p++; if ( sum >= 0x80 ) sum -= 0x80; } return sum; } #define NOFFSET 148 char * mspnof(data) char *data; { static char currbuff[17]; char *p; int m, c; p = currbuff; for ( m=0; m<16; m++ ) { c = data[NOFFSET+m]; *p++ = (isprint(c) ? c : ' '); } *p = '\0'; return(currbuff); } mspsnof(data,name) char *data; char *name; { char *p; int m; for ( p=name,m=0; *p!='\0' && m<16; p++,m++ ) data[NOFFSET+m] = *p; for ( ; m<10; m++ ) data[NOFFSET+m] = ' '; } int mspsbulk(data) char *data; { int n, c; char *p = data; flushmidi(); sendmidi(0xf0); sendmidi(0x3e); sendmidi(0x00); sendmidi(mwdevice()); sendmidi(0x50); for ( n=0; n<(SOUNDSIZE*64); n++ ) sendmidi(*p++); c = mwchecksum(data,SOUNDSIZE*64); sendmidi(c); sendmidi(EOX); return 0; } char * mwgetit(p,skip,sz,suminit) char *p; int skip; int sz; int suminit; { static char msg[100]; char *origp = p; int state = 0; int nc = 0; int sum = suminit; long begin = milliclock(); long toolong = begin + 3 * 1000 * TIMEOUT; int csum, c; while ( milliclock() < toolong && state < 3 ) { while ( STATMIDI ) { c = getmidi()&0xff; switch (state) { case 0: /* first 'skip' bytes */ if ( ++nc >= skip ) { state = 1; nc = 0; } break; case 1: *p++ = c; sum += c; if ( sum >= 0x80 ) sum -= 0x80; if ( ++nc >= sz ) { state = 2; nc = 0; } break; case 2: if ( ++nc == 1 ) csum = c; if ( nc == 2 ) state = 3; break; } } } if ( csum != sum ) { sprintf(msg,"Incorrect checksum (sum=0x%x csum=0x%x)",sum,csum); return msg; } if ( c != 0xf7 ) return "Didn't get 0xf7!?"; return NULL; } int mspgbulk(data) char *data; { int c; char *p = data; char *m; flushmidi(); sendmidi(0xf0); sendmidi(0x3e); sendmidi(0x00); sendmidi(mwdevice()); sendmidi(0x10); sendmidi(0x00); sendmidi(0xf7); if ( (m=mwgetit(p,5,SOUNDSIZE*64,0)) != NULL ) { Reason = m; return 1; } Reason = "Done."; return 0; } int mspsedit(data) char *data; { int n, c; char *p = data; flushmidi(); sendmidi(0xf0); sendmidi(0x3e); sendmidi(0x00); sendmidi(mwdevice()); sendmidi(0x42); for ( n=0; n> 12) & 0xf ; b[1] = (wn >> 8) & 0xf ; b[2] = (wn >> 4) & 0xf ; b[3] = wn & 0xf ; sendmidi(b[0]); sendmidi(b[1]); sendmidi(b[2]); sendmidi(b[3]); sum = mwchecksum(b,4); sum += mwchecksum(p,WAVESIZE); if ( sum >= 0x80 ) sum -= 0x80; for ( n=0; n> 12) & 0xf ; b[1] = (wn >> 8) & 0xf ; b[2] = (wn >> 4) & 0xf ; b[3] = wn & 0xf ; sendmidi(b[0]); sendmidi(b[1]); sendmidi(b[2]); sendmidi(b[3]); wnsum = mwchecksum(b,4); sendmidi(wnsum); sendmidi(0xf7); if ( (m=mwgetit(p,9,WAVESIZE,wnsum)) != NULL ) { Reason = m; return 1; } p += WAVESIZE; } Reason = "Done."; return 0; } /*ARGSUSED*/ int muwsedit(data) char *data; { return 0; } char * muwvnum(n) { static char v[8]; sprintf(v,"%03d",n+muwoffset()); return(v); } int mwtoffset() { static int offset = -1; if ( offset < 0 ) { #ifdef unix char *p; if ( (p=getenv("TABLEOFFSET")) != NULL ) offset = atoi(p); else #endif offset = TABLEOFFSET; } return offset; } int muwoffset() { static int offset = -1; if ( offset < 0 ) { #ifdef unix char *p; if ( (p=getenv("WAVEOFFSET")) != NULL ) offset = atoi(p); else #endif offset = WAVEOFFSET; } return offset; } int mwdevice() { static int dev = -1; if ( dev < 0 ) { #ifdef unix char *p; if ( (p=getenv("WAVEDEVICE")) != NULL ) dev = atoi(p); else #endif dev = WAVEDEVICE; } return dev; } int mwtgbulk(data) char *data; { int tn, t; int toff = mwtoffset(); char *p, *m; flushmidi(); p = data; for ( t=0; t<12; t++ ) { sendmidi(0xf0); sendmidi(0x3e); sendmidi(0x00); sendmidi(mwdevice()); sendmidi(0x05); tn = toff + t; sendmidi(tn); sendmidi(tn); /* checksum */ sendmidi(0xf7); if ( (m=mwgetit(p,6,TABLESIZE,tn)) != NULL ) { Reason = m; return 1; } p += TABLESIZE; } Reason = "Done."; return 0; } int mwtsedit(data) char *data; { return 0; } char * mwtvnum(n) { static char v[8]; sprintf(v,"%02d",n+mwtoffset()); return(v); } int mwtcvtnum(p) char *p; { int n; sscanf(p,"%d",&n); n -= mwtoffset(); return n; } int muwcvtnum(p) char *p; { int n; sscanf(p,"%d",&n); n -= muwoffset(); return n; } char * mwtnof(d) char *d; { static char buff[16]; long v1, v2, v3; v1 = ((d[0]&0xf)*16*16*16)+((d[1]&0xf)*16*16)+((d[2]&0xf)*16)+(d[3]&0xf); if ( v1 == 0xffff ) v1 = -1; v2 = ((d[4]&0xf)*16*16*16)+((d[5]&0xf)*16*16)+((d[6]&0xf)*16)+(d[7]&0xf); if ( v2 == 0xffff ) v2 = -1; v3 = ((d[8]&0xf)*16*16*16)+((d[9]&0xf)*16*16)+((d[10]&0xf)*16)+(d[11]&0xf); if ( v3 == 0xffff ) v3 = -1; sprintf(buff,"%ld,%ld,%ld...", v1, v2, v3); return(buff); } mwtsnof(data,name) char *data; char *name; { } int mwtsbulk(data) char *data; { int t; int toff = mwtoffset(); char *p = data; flushmidi(); for ( t=0; t<12; t++ ) { mwtsendit(toff+t,p); millisleep(1000); p += TABLESIZE; } return 0; } int mwtsone(t,data) int t; char *data; { flushmidi(); mwtsendit(t+mwtoffset(),data); return 0; } mwtsendit(tn,p) int tn; char *p; { int i, sum, o, n; sendmidi(0xf0); sendmidi(0x3e); sendmidi(0x00); sendmidi(mwdevice()); sendmidi(0x45); sendmidi(tn); /* force last 3 positions to -1 */ for ( i=61; i<64; i++ ) { o = i*4; p[o+0] = 0xf; p[o+1] = 0xf; p[o+2] = 0xf; p[o+3] = 0xf; } sum = mwchecksum(p,TABLESIZE); sum += tn; if ( sum >= 0x80 ) sum -= 0x80; for ( n=0; n>4) & 0xf; data[2*n+1] = v & 0xf; } return 0; } int mwtdin(data) char *data; { int n; long v; char nm[16]; for ( n=0; n<61; n++ ) { sprintf(nm,"wave%d",n); v = (data[4*n+0]&0xf)*16*16*16 + (data[4*n+1]&0xf)*16*16 + (data[4*n+2]&0xf)*16 + (data[4*n+3]&0xf); if ( v == 0xffff ) v = 0; else v++; /* The parameter values are 0 to 506, representing */ /* real values of -1 to 505. */ setval(nm,(int)v); } return 0; } int mwtdout(data) char *data; { int n, v; char nm[16]; /* Make sure wave #'s 0 and 60 are valid */ if ( getval("wave0") == 0 ) setval("wave0", 1); if ( getval("wave60") == 0 ) setval("wave60", 1); for ( n=0; n<61; n++ ) { sprintf(nm,"wave%d",n); v = getval(nm) - 1; if ( v == -1 ) data[4*n] = data[4*n+1] = data[4*n+2] = data[4*n+3] = 0xf; else { data[4*n] = (v>>12) & 0xf; data[4*n+1] = (v>>8) & 0xf; data[4*n+2] = (v>>4) & 0xf; data[4*n+3] = v & 0xf; } } return 0; } char * vissamp(v) int v; { char num[8]; static char buff[100]; int n, hgt; char *p, *pn; hgt = v / 16 + 1; sprintf(num,"%d",v); p = buff; pn = num; for ( n=strlen(num); n>0; n-- ) { *p++ = *pn++; *p++ = '~'; *p++ = 'l'; *p++ = '~'; *p++ = 'd'; } *p = '\0'; for ( n=strlen(num); n>0; n-- ) { strcat(buff,"~u"); } strcat(buff,"~u"); for ( n=0; n