page@swan.ulowell.edu (Bob Page) (03/17/89)
Submitted-by: mab@druwy.att.com (Alan Bland) Posting-number: Volume 89, Issue 73 Archive-name: audio/glib.3 # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # glib.c # yama_com.c # This archive created: Thu Mar 16 11:45:30 1989 cat << \SHAR_EOF > glib.c /* * GLIB - a Generic LIBrarian and editor for synths */ #include "glib.h" #include <ctype.h> char *Reason = ""; int Currrow = 0; /* at top of screen, for messages */ int Libbank = 0; /* from 0 to LIBBANKS-1, is the current library bank*/ int Nsynths = 0; char *Currdata; char *Yankdata; /* current 'yank' buffer (middle of screen) */ struct peredinfo *PE; /* array of per-editor miscellany */ char Buff[BUFSIZ]; int Redraw = 0; /* if non-0, edit screen is completely redrawn. */ /* parameter functions can make use of this. */ int Changed = 0; /* All the global values below are set as appropriate for the */ /* synthesizer currently being dealt with. */ int Nvoices = 0; int Voicesize =0; int Namesize = 0; int Libindex; /* from 0 to Nvoices-1 */ int Synindex; /* from 0 to Nvoices-1 */ int Channel; int Editrow; /* from 0 to NUMONSCREEN-1 */ int Editcol; /* 0==synth, 1==library */ char *Libdata; /* current library data (includes all LIBBANKS) */ /* ie. the stuff on the right side of the screen */ char *Syndata; /* current synth data (1 bank), ie. the left side */ struct paraminfo *P; /* list of parameter info */ struct labelinfo *L; /* arbitrary screen labels for edit screen */ char *Synthname; int (*Sendedit)(); /* function to send parameters to synth's edit buffer*/ int (*Datain)(); /* convert data from file-storage format to the */ /* format stored in the P[] parameter array (p_val) */ int (*Dataout)(); /* reverse of Datain */ int (*Sendone)(); /* function to send one (permanent) voice to synth */ int (*Sendbulk)(); /* function to send bulk dump to synth */ int (*Getbulk)(); /* reverse of Sendbulk */ char *(*Nameof)(); /* pulls voice name out of file-storage data */ int (*Setnameof)(); /* reverse of Nameof */ char *(*Numof)(); /* convert voice number to on-screen text */ int (*Cvtnum)(); /* convert visible voice number to std. format */ int (*Cvtanum)(); /* convert alphanumeric voice number to std. format */ /* should never define both Cvtnum and Cvtanum */ main() { int n; hello(); windinit(); initstuff(); if ( Nsynths == 0 ) windstr("Hey, the E array is empty?"); else if ( Nsynths == 1 ) { /* If there's only 1 synth, don't bother asking */ setedit(0); libinteract(); } else { while ( (n=choosesynth()) >= 0 ) { setedit(n); libinteract(); unsetedit(n); } } bye(); } /* choose a synth, returning its position in the E array */ choosesynth() { int n, pick; retry: flushconsole(); windclear(); windgoto(2,18); windstr("GLIB - A Generic Librarian/Editor"); for ( n=1; n<=Nsynths; n++ ) libchoice(n); windgoto(10+n,16); windstr("Choose your synth (or 'q' to quit) --> "); windrefresh(); pick = mouseorkey(); if ( pick == 'q' || pick == EOF ) return(-1); if ( pick != MOUSE ) pick = pick - '0'; else { int row, col; getmouse(&row,&col); /* wait until mouse goes down */ while ( statmouse() > 0 ) ; pick = row - 6; } if ( pick < 1 || pick > Nsynths ) goto retry; return(pick-1); } libchoice(n) { windgoto(6+n,27); sprintf(Buff,"%d - %s",n,E[n-1].ed_name); windstr(Buff); } initstuff() { int n, banksize, maxvsize = 0; char *p; for ( n=0; E[n].ed_name != NULL; n++ ) { if ( maxvsize < E[n].ed_vsize ) maxvsize = E[n].ed_vsize; } Nsynths = n; Currdata = alloc( maxvsize ); /* allocate an array of peredinfo structs */ PE =(struct peredinfo *)alloc((int)(Nsynths*sizeof(struct peredinfo))); for ( n=0; n<Nsynths; n++ ) { banksize = E[n].ed_nvoices * E[n].ed_vsize; p = PE[n].ed_libdata = alloc( LIBBANKS * banksize ); clrdata(p,LIBBANKS*banksize); p = PE[n].ed_syndata = alloc( banksize ); clrdata(p,banksize); p = PE[n].ed_yankdata = alloc( E[n].ed_vsize ); clrdata(p,E[n].ed_vsize); PE[n].ed_libindex = 0; PE[n].ed_synindex = 0; PE[n].ed_channel = 1; PE[n].ed_erow = 0; PE[n].ed_ecol = 0; } } clrdata(data,size) char *data; { register char *p = data, *endp = data+size; while ( p<endp ) *p++ = 0; } setedit(n) { Synthname = E[n].ed_name; Datain = E[n].ed_din; Dataout = E[n].ed_dout; Nvoices = E[n].ed_nvoices; Sendedit = E[n].ed_sedit; Sendone = E[n].ed_sone; Sendbulk = E[n].ed_sbulk; Getbulk = E[n].ed_gbulk; Nameof = E[n].ed_nof; Numof = E[n].ed_numof; Cvtnum = E[n].ed_cvtnum; Cvtanum = E[n].ed_cvtanum; Setnameof = E[n].ed_snof; Voicesize = E[n].ed_vsize; Namesize = E[n].ed_nsize; Libdata = PE[n].ed_libdata; Syndata = PE[n].ed_syndata; Yankdata = PE[n].ed_yankdata; Libindex = PE[n].ed_libindex; Synindex = PE[n].ed_synindex; Channel = PE[n].ed_channel; Editrow = PE[n].ed_erow; Editcol = PE[n].ed_ecol; clrdata(Currdata,Voicesize); P = E[n].ed_params; L = E[n].ed_labels; } unsetedit(n) { int k; PE[n].ed_libindex = Libindex; PE[n].ed_synindex = Synindex; PE[n].ed_channel = Channel; PE[n].ed_erow = Editrow; PE[n].ed_ecol = Editcol; for ( k=0; k<Voicesize; k++ ) PE[n].ed_yankdata[k] = Yankdata[k]; } /* template - show the boxes and such on the main library screen */ template() { int n, k, r; r = FIRSTROW-1; sprintf(Buff,"%s Voices",Synthname); n = 13 - strlen(Buff)/2; /* center it */ windgoto(r,n<0?0:n); windstr(Buff); r++; windgoto(r,0); for ( n=0; n<26; n++ ) windputc('='); windgoto(r,52); for ( n=0; n<26; n++ ) windputc('='); for ( n=r+1; n<(r+13); n++ ) { windgoto(n,0); windputc('|'); windgoto(n,6); windputc('|'); windgoto(n,25); windputc('|'); k=52; windgoto(n,k); windputc('|'); windgoto(n,k+6); windputc('|'); windgoto(n,k+25); windputc('|'); } windgoto(r+13,0); for ( n=0; n<26; n++ ) windputc('='); windgoto(r+13,52); for ( n=0; n<26; n++ ) windputc('='); windgoto(YANKROW-2,YANKCOL); windstr(" Yank Buffer"); windgoto(YANKROW-1,YANKCOL); windstr(" ------------- "); windgoto(YANKROW,YANKCOL); windstr(" "); windgoto(YANKROW+1,YANKCOL); windstr(" ------------- "); windrefresh(); } /* clear the message area */ clearmess() { int n; for(n=1;n<(FIRSTROW-1);n++) winderaserow(n); Currrow = 0; } /* set the current voice (ie. the synth's edit buffer) to the indicated */ /* voice. c==0 is the synth (left) side, c==1 is the library (right) side. */ editto(r,c) { int voicenum; /* Clear the existing '*' */ editchar(' ',Editrow,Editcol); editchar('*',Editrow=r,Editcol=c); if ( Editcol==0 ) { /* we're on the synth side */ voicenum = Editrow+Synindex; tocurrent(Syndata,voicenum); } else { /* we're on the lib side */ voicenum = Editrow+Libindex; tocurrent(bankvoice(0),voicenum); } } editchar(ec,r,c) { r = r + FIRSTROW + 1; if ( c == 0 ) c = LEFTSIDE-1; else c = RIGHTSIDE-1; windgoto(r,c); windputc(ec); windrefresh(); } /* control interaction on the main library bank screen */ libinteract() { int c, n, swap, voicenum, maxindex; char *p, *data; flushmidi(); drawall(); for ( ;; ) { Currrow = 0; winderaserow(Currrow); windgoto(Currrow,0); windstr("Command --> "); windrefresh(); c = mouseorkey(); if ( c == MOUSE ) { libmouse(); continue; } if ( isprint(c) ) windputc(c); clearmess(); switch ( c ) { case ' ': playnote(1); break; case '\n': #ifndef macintosh case '\r': #endif /* ignore */ break; case EOF: case 'q': return; case CH_REDRAW: drawall(); break; case 's': case 'p': swap = (c=='s')?1:0; if ( Editcol==0 ) tosyn(Synindex+Editrow,Yankdata,swap); else tolib(Libindex+Editrow,Yankdata,swap); updatedisplay(); pryankname(); break; case 'y': for(n=0;n<Voicesize;n++) Yankdata[n] = Currdata[n]; pryankname(); break; case '?': helpmessage(); break; case SCR_DOWN: maxindex = Nvoices - NUMONSCREEN; if ( Editcol==0 ) { /* we're on the synth side */ if ( (Synindex+=NUMONSCREEN/2) > maxindex ) Synindex = maxindex; } else { /* we're on the lib side */ if ( (Libindex+=NUMONSCREEN/2) > maxindex ) Libindex = maxindex; } updatedisplay(); break; case SCR_UP: if ( Editcol==0 ) { /* we're on the synth side */ if ( (Synindex-=NUMONSCREEN/2) < 0 ) Synindex = 0; } else { /* we're on the lib side */ if ( (Libindex-=NUMONSCREEN/2) < 0 ) Libindex = 0; } updatedisplay(); break; case '\033': case '`': allnotesoff(); break; case 't': transcmd(); break; case 'd': /* download from synth to display */ clrdata(Syndata,Nvoices*Voicesize); if ( readsynth(Syndata) == 0 ) syntodisplay(Synindex=0); break; case 'u': /* upload TO synth */ if ( Editcol==0 ) { voicenum = Editrow+Synindex; data = &(VOICEBYTE(Syndata,voicenum,0)); } else data = bankvoice(Editrow+Libindex); upload(data); break; case 'r': readall(); break; case 'w': writeall(); break; case 'c': setchan(); break; case 'b': /* cycle through banks, from 0 to LIBBANKS-1 */ if ( ++Libbank >= LIBBANKS ) Libbank = 0; libtodisplay(Libindex); updatedisplay(); break; case 'e': p = (*Nameof)(Currdata); if ( Editcol==0 ) { voicenum = Editrow+Synindex; data = &(VOICEBYTE(Syndata,voicenum,0)); editdata(p,data); windclear(); /* Update Currdata */ for ( n=0; n<Voicesize; n++ ) Currdata[n] = VOICEBYTE(Syndata,voicenum,n); } else { data = bankvoice(Editrow+Libindex); editdata(p,data); } drawall(); break; case 'g': /* goto a specific voice */ do_goto(); break; case CH_LEFT: if ( Editcol==1 ) editto(Editrow,0); break; case CH_DOWN: if ( Editrow < (NUMONSCREEN-1) ) editto(Editrow+1,Editcol); else { /* we're at the bottom, so try to scroll */ if ( Editcol==0 ) { /* we're on the synth side */ if (Synindex<(Nvoices-NUMONSCREEN)) Synindex++; } else { /* we're on the lib side */ if (Libindex<(Nvoices-NUMONSCREEN)) Libindex++; } updatedisplay(); } break; case CH_UP: if ( Editrow>0 ) editto(Editrow-1,Editcol); else { /* we're at the top, so try to scroll */ if ( Editcol==0 ) { /* we're on the synth side */ if (Synindex>0) Synindex--; } else { /* we're on the lib side */ if (Libindex>0) Libindex--; } updatedisplay(); } break; case CH_RIGHT: if ( Editcol==0 ) editto(Editrow,1); break; case 'f': filelist(); break; default: message("Unrecognized command! Press '?' for help."); break; } } } filelist() { char *p, *q, buff[BUFSIZ]; int n, ninline = 0, nprinted = 0; clearmess(); Currrow = -1; /* To start message on top line */ openls(); message("Files in current directory:"); strcpy(buff," "); while ( (p=nextls()) != NULL ) { /* add the next file to the line being constructed */ q = &buff[strlen(buff)]; strcpy(q,p); q += (n=strlen(p)); while ( n++ < 15 ) *q++ = ' '; *q = '\0'; if ( ninline++ > 3 ) { message(buff); if ( nprinted++ > 4 ) { message("Press any key to continue ..."); getconsole(); clearmess(); nprinted = 0; } strcpy(buff," "); ninline = 0; } } if ( ninline > 0 ) message(buff); closels(); } libmouse() { int row, col; getmouse(&row,&col); if ( row <= FIRSTROW || row > FIRSTROW+NUMONSCREEN+1 ) goto getout; if ( col < Cols/2 ) col = 0; else col = 1; row = row - FIRSTROW - 1; editto(row,col); getout: /* wait until mouse button is released */ while ( statmouse() > 0 ) ; } do_goto() { int n, r, maxindex, new_ecol; char sbuf[100], *sp; message(""); message("Where to? "); windgets(sbuf); sp = sbuf; switch(*sp++) { case 's': /* synth side */ new_ecol = 0; break; case 'l': /* library side */ new_ecol = 1; break; default: /* no change in side */ new_ecol = Editcol; sp--; /* but don't trash the first character */ break; } clearmess(); r = sscanf(sp, "%d", &n); /* this may fail - we handle it later */ if(Cvtnum != NULL) { /* convert to internal format if needed */ n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */ } if (Cvtanum != NULL) { /* convert using alphanumeric voice number */ n = (*Cvtanum)(sp) + 1; } if(r != 1) { message("type one of: sn, ln, or n"); message(" s = synth side (literal character 's')"); message(" l = library side (literal character 'l')"); message(" n = voice number to select (an integer)"); return; } if(n <= 0 || n > Nvoices) { /* 1-based */ message("Bad voice number!"); return; } /* it can be done. nuke the old '*' and change columes (if needed) */ editchar(' ', Editrow, Editcol); Editcol = new_ecol; /* try to center it */ maxindex = Nvoices - NUMONSCREEN; if(Editcol == 0) { Synindex = (n - 1) - NUMONSCREEN/2; /* 0-based */ if(Synindex < 0) { /* impossible to center */ Synindex = 0; /* so do your best */ } else if(Synindex > maxindex) { Synindex = maxindex; } Editrow = (n - 1) - Synindex; /* and put a '*' on it */ } else { Libindex = (n - 1) - NUMONSCREEN/2; /* 0-based */ if(Libindex < 0) { Libindex = 0; } else if(Libindex > maxindex) { Libindex = maxindex; } Editrow = (n - 1) - Libindex; } updatedisplay(); /* do the real work */ return; } upload(data) char *data; { int c, n; char num[16]; message(""); message("Upload TO synth:"); message(" c - current voice"); message(" a - ALL voices"); message("Choose --> "); c = getconsole(); if ( c == 'c' ) { clearmess(); if ( Sendone == NULL ) { message("Single voices can't be sent to that synth!"); return; } message("What voice number to you want to send it TO? --> "); windgets(num); clearmess(); n = atoi(num); if(Cvtnum != NULL) { /* convert to internal format if needed */ n = (*Cvtnum)(n) + 1; /* we are 1-based for user input */ } if (Cvtanum != NULL) { /* howzabout alphanumeric format? */ n = (*Cvtanum)(num) + 1; } if ( n > 0 && n <= Nvoices ) { if ( (*Sendone)(n-1,data) != 0 ) { /* 0-based on calls -SAF */ message("Unable to write data to synth!"); sprintf(Buff,"Reason: %s",Reason); message(Buff); } } else { message("Bad voice number!"); } } else if ( c == 'a' ) { clearmess(); if ( Sendbulk != NULL ) (*Sendbulk)(Syndata); else { for ( n=0; n<Nvoices; n++ ) { if ( (*Sendone)(n, &(VOICEBYTE(Syndata,n,0)) ) != 0 ) { message("Unable to write data to synth!"); sprintf(Buff,"Reason: %s",Reason); message(Buff); break; } } } /* clearmess(); */ } else { clearmess(); message("Bad choice!"); } } helpmessage() { clearmess(); sprintf(Buff,"%s,%s,%s,%s - move around e - edit current voice", STR_LEFT,STR_DOWN,STR_UP,STR_RIGHT); message(Buff); message("r - read voices from a file y - yank into buffer"); message("w - write voices to a file p - put from buffer"); message("b - cycle through library banks s - swap current voice with yank buffer"); message("t - transfer all voices f - list files in current directory"); message("d - download voices from synth c - set MIDI channel"); message("u - upload voices to synth g - 'goto' form of moving around"); message("q - quit <space> - play a note"); } updatedisplay() { if ( Editcol==0 ) { /* we're on the synth side */ syntodisplay(Synindex); editto(Editrow,Editcol); } else { /* we're on the lib side */ libtodisplay(Libindex); editto(Editrow,Editcol); } } pryankname() { char ybuff[33]; char *p; windgoto(YANKROW,YANKCOL-4); windstr(" "); strcpy(ybuff,(*Nameof)(Yankdata)); /* take off trailing blanks */ p = ybuff + strlen(ybuff) - 1; while ( p>ybuff && *p == ' ' ) *p-- = '\0'; windgoto(YANKROW,YANKCOL+7-strlen(ybuff)/2); windstr(ybuff); windrefresh(); } transcmd() { int fromc; message(""); message("Transfer ALL voices:"); message(" 1: <<----- from library bank to synth bank"); message(" 2: ----->> from synth bank to library bank"); message("1 or 2 --> "); fromc = getconsole(); windputc(fromc); if ( fromc!='1' && fromc!='2' ) { clearmess(); return; } switch ( fromc ) { case '1': copyall(bankvoice(0),Syndata); syntodisplay(Synindex); clearmess(); message("Use the 'u'pload command to actually send the synth bank voices to the synth."); break; case '2': copyall(Syndata,bankvoice(0)); libtodisplay(Libindex); clearmess(); break; } } copyall(fromdata,todata) char *fromdata; char *todata; { int n, v; for ( v=0; v<Nvoices; v++ ) for ( n=0; n<Voicesize; n++ ) VOICEBYTE(todata,v,n) = VOICEBYTE(fromdata,v,n); } message(s) char *s; { windgoto(++Currrow,0); windstr(s); windrefresh(); } setchan() { int c; message("New MIDI channel --> "); windgets(Buff); if ( (c=atoi(Buff)) <= 0 || c > 16 ) { clearmess(); message("Invalid channel!"); } else { clearmess(); Channel = c; showchan(); } } showchan() { windgoto(20,31); windstr("MIDI Channel: "); sprintf(Buff,"%d ",Channel); windstr(Buff); windrefresh(); } /* read data from a file, filling the current library bank. */ readall() { char fname[100]; FILE *f; int v, n, r; message("File name --> "); windgets(fname); OPENBINFILE(f,fname,"r"); if (f == NULL ) { sprintf(Buff,"Can't open '%s'!",fname); message(Buff); return; } /* Check the first byte. If it's 0xdd, then the format is mine. */ /* If the first byte is 0-31, it's also mine. */ n = (getc(f) & 0xff); if ( n == 0xdd || n<=31 ) { if ( n <= 31 ) ungetc(n,f); /* This is my format, just raw data. */ for ( v=0; v<Nvoices; v++ ) { char *p = bankvoice(v); for ( n=0; n<Voicesize; n++ ) *p++ = getc(f); } r = 0; } /* code for other formats would go here */ else { message("Unknown file format"); r = 1; } fclose(f); if ( r==0 ) { libtodisplay(Libindex=0); clearmess(); } } /* write current library bank to a file */ writeall() { char fname[100]; FILE *f; int v, n; message("File name --> "); windgets(fname); OPENBINFILE(f,fname,"w"); if ( f == NULL ) { sprintf(Buff,"Can't open '%s'!",fname); message(Buff); return; } putc(0xdd,f); /* magic byte to identify my format */ for ( v=0; v<Nvoices; v++ ) { char *p = bankvoice(v); for ( n=0; n<Voicesize; n++ ) putc(*p++,f); } fclose(f); clearmess(); } /* draw main library/synth voice bank screen */ drawall() { windclear(); template(); libtodisplay(Libindex); syntodisplay(Synindex); editto(Editrow,Editcol); pryankname(); showchan(); } /* * tosyn * * Store the given 'data' in in voice 'voicenum' (both in Syndata * AND on the synth itself). If swap is non-zero, the voice is swapped * with the current voice in Syndata. */ tosyn(voicenum,data,swap) char *data; { int n, t; for ( n=0; n<Voicesize; n++ ) { if ( swap ) { t = VOICEBYTE(Syndata,voicenum,n); VOICEBYTE(Syndata,voicenum,n) = data[n]; data[n] = t; } else VOICEBYTE(Syndata,voicenum,n) = data[n]; } } tolib(voicenum,data,swap) char *data; { int n, t; char *p = bankvoice(voicenum); for ( n=0; n<Voicesize; n++ ) { if ( swap ) { t = *p; *p = data[n]; data[n] = t; } else *p = data[n]; p++; } } tocurrent(data,voicenum) char *data; int voicenum; { int n; for ( n=0; n<Voicesize; n++ ) Currdata[n] = VOICEBYTE(data,voicenum,n); (*Sendedit)(Currdata); } /* * readsynth * * Read a bulk dump from the synth, with some tolerance for errors. */ readsynth(data) char *data; { if ( Getbulk == NULL ) { message("That synth is unable to dump anything!!"); return(1); } message("Trying to download data from synth..."); if ( (*Getbulk)(data) == 0 ) { clearmess(); return(0); } message("Unable to read data from synth!"); sprintf(Buff,"Reason: %s",Reason); message(Buff); message("Perhaps connections are amiss?"); return(1); } char * vnumtext(n) { static char vnbuff[6]; if ( Numof == NULL ) { sprintf(vnbuff,"%2d",n); return(vnbuff); } else return((*Numof)(n - 1)); /* keep this 0-based */ } /* * syntodisplay(n) * * Tranfer Syndata names to dialog boxes (Dxvoices) starting at n. */ syntodisplay(n) { int k, r; /* for the NUMONSCREEN dialog boxes */ for ( k=0; k<NUMONSCREEN; k++ ) { r = FIRSTROW+1+k; windgoto(r,LEFTSIDE); sprintf(Buff,"%-3s",vnumtext(n+k+1)); windstr(Buff); windgoto(r,LEFTSIDE+6); windstr(" "); /* pull the name out of the Syndata */ windgoto(r,LEFTSIDE+6); windstr((*Nameof)( & (VOICEBYTE(Syndata,n+k,0) )) ); } windrefresh(); } /* * libtodisplay * * Tranfer Libdata names to the screen, starting at voice 'firstv'. */ libtodisplay(firstv) { int k, r; windgoto(FIRSTROW-1,RIGHTSIDE-1); sprintf(Buff,"Library Voices (Bank %d)",Libbank+1); windstr(Buff); /* for the NUMONSCREEN dialog boxes */ for ( k=0; k<NUMONSCREEN; k++ ) { r = FIRSTROW+1+k; windgoto(r,RIGHTSIDE); sprintf(Buff,"%-3s",vnumtext(firstv+k+1)); windstr(Buff); windgoto(r,RIGHTSIDE+6); windstr(" "); /* pull the name out of the Libdata */ windgoto(r,RIGHTSIDE+6); windstr((*Nameof)(bankvoice(firstv+k))); } windrefresh(); } allnotesoff() { int n; /* Go through all channels. */ for ( n=0; n<15; n++ ) { sendmidi(n | 0xb0); sendmidi(0x7b); sendmidi(0x00); } } /* * Below are generic edit routines, which manage a screen display * showing parameter values, and let you roam around and make changes. * The display is managed by the contents of the P array, which * contains the name, screen location, min/max values, etc. of * each parameter. */ int Prow = 0; int Pcol = 0; int Parm = 0; /* redraw the parameter screen */ showallparms(name) char *name; { int n; char *s; windclear(); showname(name); windgoto(1,0); for(n=strlen(name)+6;n>0;n--) windputc('='); /* The L array contains arbitrary screen labels */ for ( n=0; L[n].l_text != NULL; n++ ) { windgoto(L[n].l_row,L[n].l_col); windstr(L[n].l_text); } /* Display each parameter value, and a label if there is one. */ for ( n=0; P[n].p_name != NULL; n++ ) { if ( P[n].p_flags != 0 ) continue; if ( (s=P[n].p_label) != NULL ) showstr(s,P[n].p_lrow,P[n].p_lcol,0); showparam(n,0); } windrefresh(); } showname(name) char *name; { windgoto(0,0); windstr("Name: "); windgoto(0,6); windstr(name); } showparam(n,eras) { char *p; /* The p_tovis element of the P array is a function which, given */ /* the parameter value as an argument, returns a string which is */ /* what should be displayed on the screen. */ p = (*(P[n].p_tovis))(P[n].p_val); showstr(p,P[n].p_vrow,P[n].p_vcol,eras); } showstr(p,row,col,eras) register char *p; register int col; { register int c; windgoto(row,col); while ( (c=(*p++)) != '\0' ) { switch(c){ case '~': switch( (c=(*p++)) ) { case 'u': row--; goto wgoto; case 'd': row++; goto wgoto; case 'l': col--; goto wgoto; case 'r': col++; wgoto: windgoto(row,col); break; default: windputc(eras?' ':c); col++; break; } break; default: windputc(eras?' ':c); col++; break; } } } /* Allow roaming around and changing of parameter values. */ editdata(name,data) char *name; char *data; /* vmem format */ { int c, n; windclear(); windrefresh(); /* enable all the parameters */ for ( n=0; P[n].p_name != NULL; n++ ) enableparm(n); /* Take the voice data and put it into P */ (*Datain)(data); Prow = Pcol = 0; Changed = 0; Redraw = 1; gotoparm(CH_RIGHT); /* Get to the first parameter */ for ( ;; ) { if ( Redraw ) { showallparms(name); Redraw = 0; } windgoto(Prow,Pcol); windrefresh(); c = mouseorkey(); if ( c == MOUSE ) { editmouse(); continue; } switch(c){ case CH_RIGHT: case CH_UP: case CH_DOWN: case CH_LEFT: gotoparm(c); break; case CH_REDRAW: showallparms(name); break; case 'N': /* Allow changing of voice name */ windgoto(0,5); windstr(" "); windgoto(0,6); windrefresh(); windgets(Buff); if ( Buff[0]!='\0' && Buff[0]!='\n' ) (*Setnameof)(data,Buff); showname(name=(*Nameof)(data)); Changed = 1; break; case CH_INC: adjuparm(1); break; case CH_INC2: adjuparm(4); break; case CH_INC3: adjuparm(P[Parm].p_max - P[Parm].p_min); break; case CH_DEC: adjuparm(-1); break; case CH_DEC2: adjuparm(-4); break; case CH_DEC3: adjuparm(P[Parm].p_min - P[Parm].p_max); break; #ifdef OLDSTUFF case 'a': sendaced(data); playnote(0); break; #endif case ' ': case '\n': #ifndef macintosh case '\r': #endif if ( Changed ) { (*Dataout)(data); (*Sendedit)(data); } playnote(0); break; case '\033': case '`': allnotesoff(); break; case 'q': case EOF: if ( Changed ) { (*Dataout)(data); (*Sendedit)(data); } return; default: break; } } } adjuparm(incdec) { int v, n; v = P[Parm].p_val + incdec; if ( v < (n=P[Parm].p_min) ) v = n; if ( v > (n=P[Parm].p_max) ) v = n; Changed = 1; showparam(Parm,1); /* erase the old val */ P[Parm].p_val = v; showparam(Parm,0); /* show the new val */ } editmouse() { int row, col, thisparm; getmouse(&row,&col); thisparm = closeparm(row,col); if ( thisparm == Parm ) { if ( statmouse() > 1 ) adjuparm(-1); /* right button */ else if ( statmouse() == 1 ) /* added by mab - bug fix */ adjuparm(1); /* left button */ } else { Parm = thisparm; Prow = P[Parm].p_vrow; Pcol = P[Parm].p_vcol; } } /* closeparm - Find the closest parameter */ closeparm(row,col) { register struct paraminfo *pp; register int n; int dist, mindist, minparm, dr, dc; minparm = 0; mindist = Rows + Cols; for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) { if ( pp->p_flags != 0 ) continue; if ( (dr=row-(pp->p_vrow)) < 0 ) dr = -dr; if ( (dc=col-(pp->p_vcol)) < 0 ) dc = -dc; if ( (dist=dr*dr+dc*dc) < mindist ) { minparm = n; mindist = dist; } } return(minparm); } /* playnote - play the 'auto' note */ playnote(i) { int pitch, vol, dur, chan; long endtime; pitch = getval("autopitch"); if(i == 0) { /* called from inside edit-mode */ chan = getval("autochan"); } else { /* called from the top level */ chan = Channel; } vol = getval("autovol"); dur = getval("autodur"); endtime = milliclock() + dur * 100; midinote(1,chan,pitch,vol); while ( milliclock() < endtime ) ; midinote(0,chan,pitch,vol); } /* gotoparm - search for the next parameter in the specified direction */ gotoparm(dir) { int n, k, inc, pm, orig, r = Prow, c = Pcol; if ( dir==CH_LEFT || dir==CH_RIGHT ) { if ( dir==CH_LEFT ) c--; else c++; orig = c; inc = 0; pm = -1; /* look up and down, alternately */ for ( n=2*Rows; n>0; n-- ) { r += (pm * inc++); pm = -pm; if ( r < 0 || r >= Rows ) continue; if ( dir == CH_LEFT ) { for ( c=orig; c>=0; c-- ) { if ( parmat(r,c) ) return; } } else { for ( c=orig; c<Cols; c++ ) { if ( parmat(r,c) ) return; } } } return; } if ( dir==CH_DOWN || dir==CH_UP ) { if ( dir==CH_DOWN ) r++; else r--; orig = c; while ( r >= 0 && r < Rows ) { /* look toward both sides at the same time */ inc = 0; pm = -1; for ( k=2*Cols; k>0; k-- ) { c += (pm * inc++); pm = -pm; if ( c < 0 || c >= Cols ) continue; if ( parmat(r,c) ) return; } if ( dir==CH_DOWN ) r++; else r--; c = orig; } return; } } /* paramat - return non-zero if a parameter value is at position r,c */ parmat(r,c) register int r, c; { register int n; register struct paraminfo *pp; for ( n=0,pp=P; pp->p_name != NULL; n++,pp++ ) { if ( pp->p_flags != 0 ) continue; if ( pp->p_vrow==r && pp->p_vcol==c ) { Prow = r; Pcol = c; Parm = n; return(1); } } return(0); } /* parmindex - return index (in P) of a given parameter name. */ parmindex(name) char *name; { int n; char *s; for ( n=0; (s=P[n].p_name) != NULL; n++ ) { if ( strcmp(s,name) == 0 ) return(n); } sprintf(Buff,"HEY, PARMINDEX(%s) NOT FOUND!",name); windstr(Buff); windrefresh(); return(-1); } setval(name,v) char *name; { int n; if ( (n=parmindex(name)) < 0 ) return; P[n].p_val = v; } getval(name) char *name; { int n; if ( (n=parmindex(name)) < 0 ) return(0); return(P[n].p_val); } enableparm(n) { if ( P[n].p_flags != 0 ) P[n].p_flags = 0; } disableparm(n) { if ( P[n].p_flags == 0 ) P[n].p_flags = 1; } midinote(onoff,chan,pitch,vol) { sendmidi( ((onoff==1)?(0x90):(0x80)) | ((chan-1)&0xf) ); sendmidi( pitch & 0x7f ); sendmidi( vol & 0x7f ); } static char Nbuff[16]; char *visnum(v) { sprintf(Nbuff,"%d",v); return(Nbuff); } char *visonoff(v) { if ( v==0 ) return("off"); else return("on"); } char * bankvoice(voice) { int offset = Libbank * Nvoices * Voicesize + voice * Voicesize; return(Libdata + offset); } SHAR_EOF cat << \SHAR_EOF > yama_com.c /* * GLIB - a Generic LIBrarian and editor for synths * * Yamaha Common Routines */ #define OVERLAY1 #include "glib.h" #include <ctype.h> #define DX100VSIZE 128 #define DX100NSIZE 17 char *visnum(), *visonoff(), *vism3num(), *viswave(), *vismono(); char *visfreq(), *visdx1a(); extern int Tx81; int *txindex = NULL; int txleng = 0; extern int Dopmap[]; int Tx81 = 0; /* 1 means we're talking to the TX81Z */ int Dopmap[] = { 3,1,2,0 }; int txfreq[] = { 50, 56, 62, 69, 75, 81, 87, 93, 100, 106, 112, 118, 124, 131, 137, 143, 71, 80, 88, 97, 106, 115, 123, 132, 141, 149, 158, 167, 176, 184, 193, 202, 78, 88, 98, 107, 117, 127, 137, 147, 156, 166, 176, 186, 196, 205, 215, 225, 87, 98, 108, 119, 130, 141, 151, 162, 173, 183, 194, 205, 216, 226, 237, 248, 100, 106, 112, 119, 125, 131, 137, 143, 149, 156, 162, 168, 174, 180, 187, 193, 141, 150, 159, 167, 176, 185, 194, 203, 211, 220, 229, 238, 247, 255, 264, 273, 157, 167, 177, 186, 196, 206, 216, 226, 235, 245, 255, 265, 275, 284, 294, 304, 173, 184, 195, 205, 216, 227, 238, 249, 259, 270, 281, 292, 303, 313, 324, 335, 200, 206, 212, 218, 225, 231, 237, 243, 249, 256, 262, 268, 274, 280, 287, 293, 282, 291, 300, 308, 317, 326, 335, 344, 352, 361, 370, 379, 388, 396, 405, 414, 300, 306, 312, 318, 325, 331, 337, 343, 349, 356, 362, 368, 374, 380, 387, 393, 314, 324, 334, 343, 353, 363, 373, 383, 392, 402, 412, 422, 432, 441, 451, 461, 346, 357, 368, 378, 389, 400, 411, 422, 432, 443, 454, 465, 476, 486, 497, 508, 400, 406, 412, 418, 425, 431, 437, 443, 449, 456, 462, 468, 474, 480, 487, 493, 424, 433, 441, 450, 459, 468, 476, 485, 494, 503, 511, 520, 529, 537, 546, 555, 471, 481, 491, 500, 510, 520, 530, 539, 549, 559, 569, 579, 588, 598, 608, 618, 500, 506, 512, 519, 525, 531, 537, 543, 550, 556, 562, 568, 574, 581, 587, 593, 519, 530, 540, 551, 562, 573, 584, 594, 605, 616, 627, 638, 648, 659, 670, 681, 565, 574, 582, 591, 600, 609, 617, 626, 635, 644, 652, 661, 670, 678, 687, 696, 600, 606, 612, 619, 625, 631, 637, 643, 650, 656, 662, 668, 674, 681, 687, 693, 628, 638, 647, 657, 667, 677, 687, 696, 706, 716, 726, 736, 745, 755, 765, 775, 692, 703, 713, 724, 735, 746, 757, 767, 778, 789, 800, 811, 821, 832, 843, 854, 700, 706, 712, 719, 725, 731, 737, 743, 750, 756, 762, 768, 774, 781, 787, 793, 707, 716, 724, 733, 742, 750, 759, 768, 776, 785, 794, 802, 811, 820, 828, 837, 785, 795, 804, 814, 824, 834, 844, 853, 863, 873, 883, 893, 902, 912, 922, 932, 800, 806, 812, 819, 825, 831, 837, 843, 850, 856, 862, 868, 874, 881, 887, 893, 848, 857, 865, 874, 883, 891, 900, 909, 917, 926, 935, 943, 952, 961, 969, 978, 865, 876, 886, 897, 908, 919, 930, 940, 951, 962, 973, 984, 994, 1005, 1016, 1027, 900, 906, 912, 919, 925, 931, 937, 943, 950, 956, 962, 968, 974, 981, 987, 993, 942, 952, 961, 971, 981, 991, 1001, 1010, 1020, 1030, 1040, 1050, 1059, 1069, 1079, 1089, 989, 998, 1006, 1015, 1024, 1032, 1041, 1050, 1058, 1067, 1076, 1084, 1093, 1102, 1110, 1119, 1000, 1006, 1012, 1019, 1025, 1031, 1037, 1043, 1050, 1056, 1062, 1068, 1074, 1081, 1087, 1093, 1038, 1049, 1060, 1070, 1081, 1092, 1103, 1113, 1124, 1135, 1146, 1157, 1167, 1178, 1189, 1200, 1099, 1109, 1119, 1128, 1138, 1148, 1158, 1167, 1177, 1187, 1197, 1207, 1216, 1226, 1236, 1246, 1100, 1106, 1112, 1119, 1125, 1131, 1137, 1143, 1150, 1156, 1162, 1168, 1174, 1181, 1187, 1193, 1130, 1139, 1147, 1156, 1165, 1173, 1182, 1191, 1199, 1208, 1217, 1225, 1234, 1243, 1251, 1260, 1200, 1206, 1212, 1219, 1225, 1231, 1237, 1243, 1250, 1256, 1262, 1268, 1274, 1281, 1287, 1293, 1211, 1222, 1233, 1243, 1254, 1265, 1276, 1286, 1297, 1308, 1319, 1330, 1340, 1351, 1362, 1373, 1256, 1266, 1276, 1285, 1295, 1305, 1315, 1324, 1334, 1344, 1354, 1364, 1373, 1383, 1393, 1403, 1272, 1281, 1289, 1298, 1306, 1315, 1323, 1332, 1341, 1349, 1358, 1366, 1375, 1384, 1392, 1401, 1300, 1306, 1312, 1319, 1325, 1331, 1337, 1343, 1350, 1356, 1362, 1368, 1374, 1381, 1387, 1393, 1384, 1395, 1406, 1416, 1427, 1438, 1449, 1459, 1470, 1481, 1492, 1503, 1513, 1524, 1535, 1546, 1400, 1406, 1412, 1419, 1425, 1431, 1437, 1443, 1450, 1456, 1462, 1468, 1474, 1481, 1487, 1493, 1410, 1419, 1428, 1436, 1445, 1454, 1463, 1471, 1480, 1489, 1498, 1507, 1515, 1524, 1533, 1542, 1413, 1423, 1433, 1442, 1452, 1462, 1472, 1481, 1491, 1501, 1511, 1521, 1530, 1540, 1550, 1560, 1500, 1506, 1512, 1519, 1525, 1531, 1537, 1543, 1550, 1556, 1562, 1568, 1574, 1581, 1587, 1593, 1555, 1563, 1572, 1581, 1589, 1598, 1606, 1615, 1623, 1632, 1640, 1649, 1657, 1666, 1674, 1683, 1557, 1568, 1579, 1589, 1600, 1611, 1622, 1632, 1643, 1654, 1665, 1676, 1686, 1697, 1708, 1719, 1570, 1580, 1590, 1599, 1609, 1619, 1629, 1638, 1648, 1658, 1668, 1678, 1687, 1697, 1707, 1717, 1696, 1704, 1713, 1722, 1730, 1739, 1747, 1756, 1764, 1773, 1781, 1790, 1798, 1807, 1815, 1824, 1727, 1737, 1747, 1756, 1766, 1776, 1786, 1795, 1805, 1815, 1825, 1835, 1844, 1854, 1864, 1874, 1730, 1741, 1752, 1762, 1773, 1784, 1795, 1805, 1816, 1827, 1838, 1849, 1859, 1870, 1881, 1892, 1837, 1845, 1854, 1863, 1871, 1880, 1888, 1897, 1905, 1914, 1922, 1931, 1939, 1948, 1956, 1965, 1884, 1894, 1904, 1913, 1923, 1933, 1943, 1952, 1962, 1972, 1982, 1992, 2001, 2011, 2021, 2031, 1903, 1914, 1925, 1935, 1946, 1957, 1968, 1978, 1989, 2000, 2011, 2022, 2032, 2043, 2054, 2065, 1978, 1986, 1995, 2004, 2012, 2021, 2029, 2038, 2046, 2055, 2063, 2072, 2080, 2089, 2097, 2106, 2041, 2051, 2061, 2070, 2080, 2090, 2100, 2110, 2119, 2129, 2139, 2149, 2159, 2168, 2178, 2188, 2076, 2087, 2098, 2108, 2119, 2130, 2141, 2152, 2162, 2173, 2184, 2195, 2206, 2216, 2227, 2238, 2120, 2128, 2137, 2145, 2154, 2162, 2171, 2179, 2188, 2196, 2205, 2213, 2222, 2230, 2238, 2247, 2198, 2208, 2218, 2227, 2237, 2247, 2257, 2267, 2276, 2286, 2296, 2306, 2316, 2325, 2335, 2345, 2249, 2260, 2271, 2281, 2292, 2303, 2314, 2325, 2335, 2346, 2357, 2368, 2379, 2389, 2400, 2411, 2355, 2365, 2375, 2384, 2394, 2404, 2414, 2424, 2433, 2443, 2453, 2463, 2473, 2482, 2492, 2502, 2422, 2433, 2444, 2454, 2465, 2476, 2487, 2498, 2508, 2519, 2530, 2541, 2552, 2562, 2573, 2584, 2595, 2606, 2617, 2627, 2638, 2649, 2660, 2671, 2681, 2692, 2703, 2714, 2725, 2735, 2746, 2757 }; /* * dxtxdin * * Take info from 'data' and stuff values in the P array, by using * the setval (and setopval) functions. 'data' is the Yamaha VMEM format. * This function works for both the dx100 and tx81z. */ dxtxdin(data) char *data; { int dop, adop, n, crs, fin, v; setdxtx(); if ( Tx81 ) txinit(); for ( n=1; n<=4; n++ ) { dop = Dopmap[n-1]*10; adop = Dopmap[n-1]*2; setopval(n,"attack",data[0+dop]); setopval(n,"decay1",data[1+dop]); setopval(n,"level1",data[4+dop]); setopval(n,"decay2",data[2+dop]); setopval(n,"release",data[3+dop]); setopval(n,"keyscale",data[5+dop]); setopval(n,"ampmod",(data[6+dop]>>6)&01); setopval(n,"egbias",(data[6+dop]>>3)&07); setopval(n,"velocity",data[6+dop]&07); setopval(n,"outlevel",data[7+dop]); if ( Tx81 ) { crs = data[8+dop]; fin = (data[74+adop]) & 017; v = freqin(crs,fin); setopval(n,"freq",v); } else setopval(n,"freq",data[8+dop]); setopval(n,"keyrate",data[9+dop]>>3); setopval(n,"detune",data[9+dop]&07); if ( Tx81 ) { setopval(n,"egsft",(data[73+adop]>>4)&03); setopval(n,"fix",(data[73+adop]>>3)&01); setopval(n,"wave",(data[74+adop]>>4)&07); } } setval("lfosync",(data[40]>>6)&01); setval("feedback",(data[40]>>3)&07); setval("algorithm",data[40]&07); setval("lfospeed",data[41]); setval("lfodelay",data[42]); setval("pmoddepth",data[43]); setval("amoddepth",data[44]); setval("pmodsens",(data[45]>>4)&07); setval("amodsens",(data[45]>>2)&03); setval("lfowave",data[45]&03); setval("transpose",data[46]); setval("pitchbend",data[47]); setval("portatime",data[49]); setval("modprange",data[51]); setval("modarange",data[52]); setval("breathprange",data[53]); setval("breatharange",data[54]); setval("breathpbias",data[55]); setval("breathegbias",data[56]); setval("playmode",(data[48]>>3)&01); setval("susfoot",(data[48]>>2)&01); setval("portfoot",(data[48]>>1)&01); setval("portmode",data[48]&01); setval("autochan",Channel); if ( Tx81 ) { setval("reverbrate",data[81]&07); setval("fcpitch",data[82]); setval("fcamp",data[83]); } } /* * dxtxdout * * Take (possibly changed) parameters values out of the P array and * put them back into 'data'. 'data' is in the Yamaha VMEM format. * This works for both the dx100 and tx81z. */ dxtxdout(data) char *data; { int dop, n, crs, fin; for ( n=1; n<=4; n++ ) { dop = Dopmap[n-1]*10; data[0+dop] = getopval(n,"attack"); data[1+dop] = getopval(n,"decay1"); data[4+dop] = getopval(n,"level1"); data[2+dop] = getopval(n,"decay2"); data[3+dop] = getopval(n,"release"); data[5+dop] = getopval(n,"keyscale"); data[6+dop] = getopval(n,"ampmod")<<6 | getopval(n,"egbias")<<3 | getopval(n,"velocity"); data[7+dop] = getopval(n,"outlevel"); data[9+dop] = getopval(n,"keyrate")<<3 | getopval(n,"detune"); if ( ! Tx81 ) { data[8+dop] = getopval(n,"freq"); } else { freqout(getopval(n,"freq"),&crs,&fin); data[8+dop] = crs; dop = Dopmap[n-1]*2; data[73+dop] = getopval(n,"egsft")<<4 | getopval(n,"fix")<<3 /* | getopval(n,"fixrg") */; data[74+dop] = getopval(n,"wave")<<4 | fin; } } data[40] = getval("lfosync")<<6 | getval("feedback")<<3 | getval("algorithm"); data[41] = getval("lfospeed"); data[42] = getval("lfodelay"); data[43] = getval("pmoddepth"); data[44] = getval("amoddepth"); data[45] = getval("pmodsens")<<4 | getval("amodsens")<<2 | getval("lfowave"); data[46] = getval("transpose"); data[47] = getval("pitchbend"); data[49] = getval("portatime"); data[51] = getval("modprange"); data[52] = getval("modarange"); data[53] = getval("breathprange"); data[54] = getval("breatharange"); data[55] = getval("breathpbias"); data[56] = getval("breathegbias"); data[48] = (unsigned) ( getval("playmode")<<3 | getval("susfoot")<<2 | getval("portfoot")<<1 | getval("portmode")); if ( Tx81 ) { data[81] = getval("reverbrate"); data[82] = getval("fcpitch"); data[83] = getval("fcamp"); } Channel = getval("autochan"); } setdxtx() { if ( strcmp(Synthname,"DX-100")==0 ) Tx81 = 0; else Tx81 = 1; } setopval(n,str,v) char *str; { char buff[32]; sprintf(buff,"op%d%s",n,str); setval(buff,v); } getopval(n,str) char *str; { char buff[32]; sprintf(buff,"op%d%s",n,str); return(getval(buff)); } /* * The routines below are used (in the P array) for printing the * values of various parameters (e.g. the vism3num routine prints * the value-3, which is appropriate for the 'detune' parameter. */ char Numbuff[8]; char *visnum(); char * vis1num(v) { sprintf(Numbuff,"%d",v+1); return(Numbuff); } char * vism3num(v) { sprintf(Numbuff,"%d",v-3); return(Numbuff); } char *visonoff(); char * vismono(v) { if ( v==0 ) return("poly"); else return("mono"); } /* 4 2 4 2 4 4 | | | | | 4 | 2---3 ---3 3 4 2 3 1 4 ___|___ 1 2 3 | | | | | | | | | | | |__|__| 1 1 1--- 1--- 2 3 1 2 3 |__| |__|__| 1 2 3 4 |__|__|__| */ char *Algostr[] = { "1 ~d2---3~u~l|~u~l4~d~d~d~l~l~l~l~l|~l~d1", "2 ~d---3~l~l~l~l~u| |~l~l~l~l~u2 4~l~d~d~d|~l~d1", "3 ~d3 4~l~l~l~l~u|~l~u2~l~d~d~d| |~d~l~l~l~l1---", "4 ~d2 3~l~u|~u~l4~l~d~d~d~l~l~l| |~l~l~l~l~d1---", "5 ~d~u1 4~d~l~l~l~l| |~d~l~l~l~l2 3~d~l~l~l~l----", "6 ~d| | |~u~l~l~l~l~l~l~l___|___~u~l~l~l~l4~l~d~d~d~l~l~l1 2 3~d~l~l~l~l~l~l~l|__|__|", "7 ~d1 2 3~u~l|~u~l4~l~d~d~d~l~l~l~l~l~l|__|__|", "8 ~d1 2 3 4~d~l~l~l~l~l~l~l~l~l~l|__|__|__|" }; char * visdx1a(v) { if ( v >= 0 && v <= 7 ) return(Algostr[v]); else return("????"); } char * viswave(v) { switch(v){ case 0: return("saw up"); case 1: return("square"); case 2: return("triangle"); case 3: return("s/hold"); default: return("???"); } } char *Freqstr[] = { /* values from 0 to 63 */ "0.50 ", "0.71 ", "0.78 ", "0.87 ", "1.00 ", "1.41 ", "1.57 ", "1.73 ", "2.00 ", "2.82 ", "3.00 ", "3.14 ", "3.46 ", "4.00 ", "4.24 ", "4.71 ", "5.00 ", "5.19 ", "5.65 ", "6.00 ", "6.28 ", "6.92 ", "7.00 ", "7.07 ", "7.85 ", "8.00 ", "8.48 ", "8.65 ", "9.00 ", "9.42 ", "9.89 ", "10.00", "10.38", "10.99", "11.00", "11.30", "12.00", "12.11", "12.56", "12.72", "13.00", "13.84", "14.00", "14.10", "14.13", "15.00", "15.55", "15.57", "15.70", "16.96", "17.27", "17.30", "18.37", "18.84", "19.03", "19.78", "20.41", "20.76", "21.20", "21.98", "22.49", "23.55", "24.22", "25.95" }; char * visfreq(v) { if ( v >=0 && v <= 63 ) return ( Freqstr[v] ); else return("????"); } /* * dx1sedit * * Send a single voice to the edit buffer of the DX. */ dx1sedit(data) char *data; { setdxtx(); if ( Tx81 ) sendaced(data); sendvced(data); } sendvced(data) char *data; { char vdata[DX100VSIZE]; int n, cksum, c; clrdata(vdata,DX100VSIZE); vmemtovced(data,vdata); sendmidi(0xf0); sendmidi(0x43); sendmidi(Channel-1); /* channel # */ sendmidi(0x03); /* format type */ sendmidi(0x00); /* byte count */ sendmidi(0x5d); /* byte count */ cksum = 0; for ( n=0; n<93; n++ ) { sendmidi(c = (int)(vdata[n])); cksum += c; } sendmidi((-cksum) & 0x7f); sendmidi(EOX); } sendaced(data) char *data; { char *p, vdata[DX100VSIZE]; int n, cksum, c; clrdata(vdata,DX100VSIZE); vmemtoaced(data,vdata); sendmidi(0xf0); sendmidi(0x43); sendmidi(Channel-1); /* channel # */ sendmidi(0x7e); /* format type */ sendmidi(0x00); /* byte count */ sendmidi(0x21); /* byte count */ p = "LM 8976AE"; cksum = 0; while ( (c=(int)(*p++)) != '\0' ) { sendmidi(c); cksum += c; } for ( n=0; n<23; n++ ) { sendmidi(c=(int)(vdata[n])); cksum += c; } sendmidi((-cksum) & 0x7f); sendmidi(EOX); } /* * vmemtovced * * convert a vmem format voice to vced format. */ vmemtovced(data,vdata) char *data; char *vdata; { int vop, dop, n; for ( n=0; n<4; n++ ) { /* vop = Dopmap[n]*13; */ vop = Dopmap[n]*13; dop = Dopmap[n]*10; vdata[vop+0] = data[dop+0]; /* attack rate */ vdata[vop+1] = data[dop+1]; /* decay 1 rate */ vdata[vop+2] = data[dop+2]; /* decay 2 rate */ vdata[vop+3] = data[dop+3]; /* release rate */ vdata[vop+4] = data[dop+4]; /* decal 1 level */ vdata[vop+5] = data[dop+5]; /* keyboard scaling level */ vdata[vop+6] = (data[dop+9]>>3);/* keyboard scaling rate */ vdata[vop+7] = (data[dop+6]>>3)&7; /* eg bias sens. */ vdata[vop+8] = (data[dop+6]>>6)&1; /* amp. mod. enable */ vdata[vop+9] = (data[dop+6]&7); /* key velocity */ vdata[vop+10] = data[dop+7]; /* output level */ vdata[vop+11] = data[dop+8]; /* osc. frequency */ vdata[vop+12] = (data[dop+9]&7); /* detune */ } vdata[52] = (data[40]&7); /* algorithm */ vdata[53] = (data[40]>>3)&7; /* feedback level */ vdata[54] = data[41]; /* lfo speed */ vdata[55] = data[42]; /* lfo delay */ vdata[56] = data[43]; /* pitch modulation depth */ vdata[57] = data[44]; /* amplitude modulation depth */ vdata[58] = (data[40]>>6)&1; /* lfo sync */ vdata[59] = data[45]&3; /* lfo wave */ vdata[60] = (data[45]>>4)&7; /* pitch modulation sens. */ vdata[61] = (data[45]>>2)&3; /* amp. modulation sens. */ vdata[62] = data[46]; /* transpose */ vdata[63] = (data[48]>>3)&1; /* play mode (poly/mono) */ vdata[64] = data[47]; /* pitch bend range */ vdata[65] = (data[48]&1); /* portamento mode */ vdata[66] = data[49]; /* portamento time */ vdata[67] = data[50]; /* foot volume range */ vdata[68] = (data[48]>>2)&1; /* sustain foot switch */ vdata[69] = (data[48]>>1)&1; /* portamento foot switch */ vdata[70] = (data[48]>>4)&1; /* chorus switch */ vdata[71] = data[51]; /* mod. wheel pitch mod. range */ vdata[72] = data[52]; /* mod. wheel ampli. mod. range */ vdata[73] = data[53]; /* breath pitch mod. range */ vdata[74] = data[54]; /* breath ampli. mod. range */ vdata[75] = data[55]; /* breath control pitch bias range */ vdata[76] = data[56]; /* breath control EG bias range */ for ( n=77; n<93; n++ ) /* voice name AND pitch EG rates */ vdata[n] = data[n-20]; } /* * vmemtoaced * * Convert a vmem format voice to aced format (TX81Z). */ vmemtoaced(data,adata) char *data; char *adata; { int vop, aop, n; for ( n=0; n<4; n++ ) { vop = 73 + Dopmap[n]*2; aop = Dopmap[n]*5; adata[0+aop] = (data[vop]>>3) & 01; /* fixed freq (0,1) */ adata[1+aop] = data[vop] & 07; /* fixed freq range (0-7) */ adata[2+aop] = data[vop+1] & 017; /* freq range fine (0-15) */ adata[3+aop] = (data[vop+1]>>4) & 07; /* op. waveform (0-7) */ adata[4+aop] = (data[vop]>>3) & 03; /* EG shift (0-3) */ } adata[20] = data[81] & 07; /* reverb rate */ adata[21] = data[82]; /* Foot controller pitch */ adata[22] = data[83]; /* Foot controller amp. */ } #ifdef OLD /* * Send a single parameter value. */ sendparam(param,val) { sendmidi(0xf0); sendmidi(0x43); sendmidi(0x10); /* Channel? */ sendmidi(0x12); sendmidi(param); sendmidi(val); sendmidi(EOX); } /* * remotely press a key on the DX */ presskey(key,val) { sendmidi(0xf0); sendmidi(0x43); sendmidi(0x10); /* Channel? */ sendmidi(0x08); sendmidi(key); sendmidi(val); sendmidi(EOX); } /* * tovmem * * convert a vced format voice to vmem format. */ tovmem(vdata,data) char *vdata; /* vced format data */ char *data; /* vmem format */ { int vop, dop, n; for ( n=0; n<4; n++ ) { vop = Dopmap[n]*13; dop = Dopmap[n]*10; data[dop+0] = vdata[vop+0]; /* attack rate */ data[dop+1] = vdata[vop+1]; /* decay 1 rate */ data[dop+2] = vdata[vop+2]; /* decay 2 rate */ data[dop+3] = vdata[vop+3]; /* release rate */ data[dop+4] = vdata[vop+4]; /* decal 1 level */ data[dop+5] = vdata[vop+5]; /* keyboard scaling level */ /* amp. mod. enab/eg bias sens/key velocity */ data[dop+6]=(vdata[vop+8]<<6) | (vdata[vop+7]<<3) | vdata[vop+9]; data[dop+7] = vdata[vop+10]; /* output level */ data[dop+8] = vdata[vop+11]; /* osc. frequency */ /* key scaling rate/detune */ data[dop+9] = (vdata[vop+6]<<3) | vdata[vop+12]; } /* lfo sync/feedback level/algorithm */ data[40] = (vdata[58]<<6) | (vdata[53]<<3) | vdata[52]; data[41] = vdata[54]; /* lfo speed */ data[42] = vdata[55]; /* lfo delay */ data[43] = vdata[56]; /* pitch modulation depth */ data[44] = vdata[57]; /* amplitude modulation depth */ /* pitch mod. sens/amp. mod. sens/lfo wave */ data[45] = (vdata[60]<<4) | (vdata[61]<<2) | vdata[59]; data[46] = vdata[62]; /* transpose */ /* chorus/playmode/sustain/portamento-foot/portamento-mode */ data[48] = (vdata[70]<<4)|(vdata[63]<<3)|(vdata[68]<<2)|(vdata[69]<<1) | vdata[65]; data[47] = vdata[64]; /* pitch bend range */ data[49] = vdata[66]; /* portamento time */ data[50] = vdata[67]; /* foot volume range */ data[51] = vdata[71]; /* mod. wheel pitch mod. range */ data[52] = vdata[72]; /* mod. wheel ampli. mod. range */ data[53] = vdata[73]; /* breath pitch mod. range */ data[54] = vdata[74]; /* breath ampli. mod. range */ data[55] = vdata[75]; /* breath control pitch bias range */ data[56] = vdata[76]; /* breath control EG bias range */ for ( n=77; n<93; n++ ) /* voice name AND pitch EG rates */ data[n-20] = vdata[n]; } #endif /* dx1nof - return a pointer to the voice name buried in data */ char * dx1nof(data) char *data; { static char currbuff[DX100NSIZE+1]; char *p; int m; p = currbuff; for ( m=0; m<10; m++ ) *p++ = data[57+m]; *p = '\0'; return(currbuff); } /* dx1snof - set the voice name buried in data to name */ dx1snof(data,name) char *data; char *name; { char *p; int m; for ( p=name,m=0; *p!='\0' && m<10; p++,m++ ) data[57+m] = *p; for ( ; m<10; m++ ) data[57+m] = ' '; } /* dx1sbulk - send a bulk dump to the DX-100 */ dx1sbulk(data) char *data; { int c, v, n, cksum; sendmidi(0xf0); sendmidi(0x43); sendmidi(Channel-1); /* Channel # */ sendmidi(0x04); sendmidi(0x20); sendmidi(0x00); cksum = 0; /* send 32 voices worth of data */ for ( v=0; v<32; v++ ) { for ( n=0; n<DX100VSIZE; n++ ) { /* The DX100 can only handle 24 voices (but needs */ /* to have 32 voices worth of data sent, anyway) */ if ( v >= 24 && ( ! Tx81 ) ) c = 0; else c = VOICEBYTE(data,v,n); sendmidi(c & 0xff); cksum += c; } } sendmidi((-cksum) & 0x7f); sendmidi(0xf7); } /* dx1gbulk - Request and read a bulk dump from the DX-100 */ dx1gbulk(data) char *data; { int c, n, v, b1, b2, cksum, ret = 1; long begin, toolong; setdxtx(); flushmidi(); sendmidi(0xf0); sendmidi(0x43); sendmidi(0x20 | (Channel-1) ); /* Channel # */ sendmidi(4); /* 4 == 32 voice bulk dump */ sendmidi(EOX); /* EOX */ begin = milliclock(); toolong = begin + 1000 * TIMEOUT; /* wait for the x43 byte starting the dump */ while ( milliclock() < toolong ) { if ( STATMIDI && (c=(getmidi() & 0xff)) == 0x43 ) break; } if ( c != 0x43 ) { Reason = "Timeout waiting for 0x43"; goto getout; } getmidi(); /* channel # */ getmidi(); /* format # */ getmidi(); /* byte count high byte */ getmidi(); /* byte count low byte */ cksum = 0; /* 32 voices are dumped */ for ( v=0; v<32; v++ ) { for ( n=0; n<DX100VSIZE; n++ ) { /* twiddle your thumbs, but not forever */ while ( ! STATMIDI ) { if ( milliclock() > toolong ) goto timeout; /* the end of an era */ } c = (getmidi() & 0xff); /* Ignore non-data bytes ? */ if ( c & 0x80 ) continue; /* compute checksum */ cksum += c; /* Only 24 voices are used on the DX100 */ if ( v < 24 || Tx81 ) VOICEBYTE(data,v,n) = c; } } timeout: if ( v < 32 ) { Reason = "Timeout while reading!"; goto getout; } b1 = (getmidi() & 0xff); /* Checksum */ b2 = (getmidi() & 0xff); /* EOX */ cksum = (-cksum) & 0x7f; /* convert to what we must match */ if ( b2 != EOX ) Reason = "EOX not received"; else if ( b1 != cksum ) { static char ckbuff[80]; sprintf(ckbuff,"Checksum doesn't match (got %d expected %d)",b1,cksum); /* Reason = "Checksum doesn't match"; */ Reason = ckbuff; } else { Reason = ""; ret = 0; /* all's well */ } getout: return(ret); } #ifdef OLDSTUFF dxchecksum(data) char *data; { int v, n, s=0; for ( v=0; v<DX100NVOICES; v++ ) { for ( n=0; n<DX100VSIZE; n++ ) { s += (int)(VOICEBYTE(data,v,n)); while ( s > 128 ) s -= 128; } } return(128-s); } #endif freqin(crs,fin) { int n, f; txinit(); f = txfreq[crs*16+fin]; for ( n=0; n<txleng; n++ ) { if ( txfreq[txindex[n]] == f ) return(n); } return(0); } freqout(v,acrs,afin) int *acrs; int *afin; { int i; i = txindex[v]; *acrs = i/16; *afin = i%16; } txinit() { int n, k; char *parm; if ( txindex != NULL ) return; /* create an array of indexes into txfreq, giving a sorted */ /* list of unique frequencies. */ txindex = (int *) alloc(sizeof(int) * 64 * 16); for ( n=0; n<64; n++ ) { for ( k=0; k<16; k++ ) { int freq = txfreq[n*16+k]; register int i, f; register int *p, *endp; /* insertion sort, starting from top of already */ /* sorted list, since the values we're inserting */ /* are almost sorted already. */ for ( i=txleng-1; i>=0; i-- ) { if ( (f=txfreq[txindex[i]]) < freq ) break; if ( f == freq ) goto dontadd; } i++; /* shift everything up one */ p = &txindex[txleng]; endp = &txindex[i]; for ( ; p>endp; p-- ) *p = *(p-1); txindex[i] = 16*n+k; txleng++; dontadd: ; } } /* set the maximum value for the frequency parameters */ parm = "op#freq"; for ( n=1; n<=4; n++ ) { parm[2] = '0' + n; if ( (k=parmindex(parm)) >= 0 ) P[k].p_max = txleng-1; } } SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.