// cond.cpp -- conductor program -- float tempo -- 100ms retrigger time // Date: Thu Aug 17 18:04:10 PDT 2000 // #include "batonImprov.h" typedef unsigned char uchar; typedef unsigned short ushort; typedef unsigned int uint; #define NOTECONTROL (c+1) // #define NOTECONTROL (1) //////////////////////////////////////////////////////////////////////////// // // #include "cond.h" // #define NOCONTROL 16 /* max number of patchchords for control changes */ #define CHORDSIZE 15 /* max no of notes in a chord */ #define VOICES 25 /* maximum no of voices */ #define SCORERECSIZE 30 /* max no bytes in a score record */ #define NOTE 1 #define TRIG 2 /* / */ #define REST 4 /* r */ #define PROGRAMCHANGE 5 /* t */ #define NOOP 6 #define SETCHANNEL 7 /* h */ #define TEMPO 8 /* v or V */ #define UPPEDAL 9 /* P */ #define PEDAL 10 /* p */ #define CONTTEMPO 11 /* w */ #define MARK 12 /* m */ #define KEYVELOCITY 13 /* k */ #define BATON2 14 /* T */ #define DOTEQUALS 15 /* j */ #define INIT 19 /* I */ #define FTEMP 20 /* W */ #define CONTCONTROL 21 /* q */ #define MNOTEON 22 #define MNOTEOFF 23 #define NOACTION 24 #define STICKLEVELS 25 #define SYSEX 26 #define PITCHBEND 27 #define MEASURE 36 // nc.c and ns constants #define SMOOTHING 0.5 /* 0.0==infinite smoothing, 1.0==no smoothing */ #define X 1 #define Y 2 #define Z 3 #define P 4 #define V 5 #define S 6 short a[28]; short abeatset; short arg1; short arg2; long beatsum; long beat_time; short b[28],baton2; short bufchan; uchar bufp; short b1; short b2; uchar calf[2048]; short chan; short channel[VOICES]; short chord[VOICES*CHORDSIZE]; short chordpi[VOICES]; short chordp[VOICES]; short controler; short cont4; short contp; short ctempo; short contpatch; short contch[NOCONTROL]; short contno[NOCONTROL]; // arrays defining patchcords short controlerfn[NOCONTROL]; short controlerfnv[NOCONTROL]; short contbalance[NOCONTROL]; short sustped[16]; long contime; short dataa; short dist; short dotchange; short dotro; short dotrn; short diff[11]; short dx; short dr0; short drumset1; short drumset2; short dynamic[VOICES]; short dyntype[VOICES]; long dur; short endscoreflag; short hungnote; short hungnoteno; long ibeat; long itim; short interval; short kk; short keych,keyno,keyvel; long keytime; short mark; short midich; short midichar; short minus14; short minus15; short mm; uchar midibuf[256]; uchar midirbuf[256]; uchar midipi; uchar midipo; uchar midirpi; uchar midirpo; short num,nextkeyno,noteon,nextbeat,nobat,needscore; short notenumb1,notenumb2,noteon1,noteon2; long nexttime,nextnotetime; short zpause; short plus14; short plus15; short potvalue,pot[5]; long pt_time,pt_beat; short prog; short recordmark,retoff,retseg,restpoint,recordcnt,recordlength; long samptime; short samp,scanmark,scancount,sustain; short scorestate,scoreadp,scorkd[SCORERECSIZE],scorkdend; short stick,st0,st1,st2,set12p,sticklevelflag; short sum; short suminc; short range; short t[28]; short temposet; short thru; long threshtime; short tranftype; extern long t_time;long t_times,t_tdata,t_tkey; short volume[16],vtemp,volumeconst,volx; short ivalue,ipvalue,invalue; float value,pvalue,nvalue; float contval[NOCONTROL]; short whack; short x1,x2,x[3]; short x1s,x1cont[16],x1type[16],x2s,x2cont[16],x2type[16]; short y11,y2,y[3]; short y1s,y1cont[16],y1type[16],y2s,y2cont[16],y2type[16]; short zp,z1,z2,z[3]; short zero1x,zero1y,zero2x,zero2y,zcalib; char midif[100]; char scoref[100]; char scorepf[100]; short newdotp; short scoresok; //////////////////////////////////////////////////////////////////////////// // Global variables: int temp1; // int temp2; // int playmode; // short sysexmessage; // short midich1; // short maxscore; // short minscore; // short sendingscore; // short timecount; // uchar midi_port; // uchar midififo[256]; // uint midiip; // uint midiop; // uint midiipsav; // short midimessages; // short sysexcase; // short scorechars; // short charcount; // short endplayscoreflag; // uint scoreip; // uint scoreop; // long controlchangetime; // long lastwhacktime; // int startmeasure; // int scan; // int discard; // int measure; // int readscore; // int ii; // FILE *fp2; // short buf[17]; // int b14minusdown; // int b14minusup; // int b15minusdown; // int b15minusup; // float tempo; // float temposave; // // Function definitions int keyvelfun (int); int getch (void); int getnextchar (void); void smoothandsend (void); void pcc (void); void loadplay (void); void playrecord (void); void readscorez (void); void stkcontrol (void); /*--------------------beginning improvization algorithms------------------*/ /*---------------------initialization algorithms--------------------------*/ void description(void) { cout << "CONDUCTOR COMMANDS s--select score z--start playing\n" " b--stop playing n--toggle no baton mode on/off\n" << endl; } void initialization(void) { startmeasure=1; eventIdler.setPeriod(0); } void initializecond(void) { int i; //whackint1=0; sysexcase = midiip = midiop = midimessages = 0; for (i=0; i controlchangetime) { // if midibuf[] empty send cont changes controlchangetime = t_time+2; if (contno[contp]) { stkcontrol(); //send data from next patchchord } /*contno[j] is zero for patchchord which is not in use */ if (++contp==NOCONTROL) { contp=0; } } if (zpause) goto endmainloop; if (nobat) { // in nobaton mode, play score at constant tempo (=tempo) if (t_time > nexttime) { playrecord(); if (playmode) { readscorez(); } nexttime = t_time + (nextbeat*(int)tempo); } } else { if (ctempo) { // continuous tempo control by y1 if (t_time > nexttime){ playrecord(); if (playmode) { readscorez(); } if (zt1>set1 && vtemp) { if (!yt1) { yt1=1; } tempo = ((int)temposave*64)/yt1; } nexttime = t_time + (nextbeat*(int)tempo); } } else { if (whack1) { // baton 1 control of tempo whack1 = 0; if ((t_time-lastwhacktime)<100) { goto falsewhack; } lastwhacktime = t_time; beat_time = trigtime1; itim = trigtime1 - pt_time; while (scorkd[0]!=TRIG) { if (scorkd[0] == NOTE) { scorkd[0]=REST; /*skip unplayed notes*/ } playrecord(); if (playmode) { readscorez(); } } // compute new tempo from time between last two baton beats ibeat = beatsum-pt_beat; pt_beat=beatsum; pt_time=beat_time; if (dotchange) { ibeat = (ibeat*dotrn)/dotro; dotchange = 0; } if (!temposet) { tempo = temposave = (short)(itim/ibeat); } else { temposet=0; } if (playmode) { readscorez(); } nexttime = t_time+(nextbeat*(int)tempo); falsewhack:; } else { if(scorkd[0]!=TRIG){ if(t_time>nexttime){ playrecord(); if (playmode) { readscorez(); } nexttime = t_time + (nextbeat*(int)tempo); } } } } } endmainloop:; } } /*--------------------triggered algorithms--------------------------------*/ void stick1trig(void) { } void stick2trig(void) { } void b14plustrig(void) { // clmidi();offmidi();t_sched_off();t_stop();exit(0); } void b15plustrig(void) { cout << "b15+ trigger" << endl; } void b14minusuptrig(void){ b14minusdown=1; scan=1; startmeasure=measure; } void b14minusdowntrig(void) {b14minusup =1; } void b15minusuptrig(void) {b15minusdown =1; } void b15minusdowntrig(void) {b15minusup =1; } void keyboardchar(int testch){ switch(testch){ case 'b': playmode = 0; break; case 's': //select and compile score baton.positionReportingOff(); cout << "type name of score file: "; echoKeysOn(); cin.getline(scoref, 64, '\n'); echoKeysOff(); cout << "Got here and scoref = " << scoref << endl; strcpy(scorepf, scoref); strcat(scorepf, ".p"); strcpy(midif, scoref); strcat(midif, ".mid"); if ((fp2=fopen(scorepf,"r+b")) != NULL) { cout << "playing existing .p file" << endl; cout << "type COMMAND (type z to start playing)" << endl; newdotp=0; } else{ cout << "SCORE NOT FOUND" << endl; } break; case 'z': baton.positionReportingOn(); loadplay(); pcc(); break; case 'n': //toggle no baton mode if(nobat){nobat=0;printf("NOBAT MODE OFF\n");} else{nobat=1;printf("NOBAT MODE ON\n");} break; case 'm': //set startmeasure cout << "startmeasure = "; echoKeysOn(); cin >> startmeasure; echoKeysOff(); break; default: printf("UNKNOWN COMMAND \n"); pcc();break; } } void finishup(void) { } ////////////////////////////// // // loadplay -- // void loadplay(void) { int ii; for (ii=0;ii<16;ii++) { control_change(ii, 64, 0); } nexttime = t_time; while (t_time < nexttime); if ((fp2=fopen(scorepf,"r+b")) != NULL) { cout << "PLAY SCORE.P FILE" << endl; initializecond(); } else { cout << "SCORE.P FILE NOT FOUND\ntype COMMAND" << endl; scoresok = 0; } } ////////////////////////////// // // stkcontrol -- coupling batons to control changes // void stkcontrol(void) { int i,j; value=-1; i=controlerfn[contp]; j=controlerfnv[contp]; switch(i){ case X: if (j == 1) { value=xt1; smoothandsend(); } if(j==2) { value=xt2; smoothandsend(); } if(j==11) { value=127-xt1; smoothandsend(); } if (j==21) { value = 127-xt2; smoothandsend(); } break; case Y: if(j==1 ){value=yt1;smoothandsend();} if(j==2 ){value=yt2;smoothandsend();} if(j==11 ){value=127-yt1;smoothandsend();} if(j==21 ){value=127-yt2;smoothandsend();} break; case Z: if(j==1){value=zt1;smoothandsend();} if(j==2){value=zt2;smoothandsend();} if(j==11){value=127-zt1;smoothandsend();} if(j==21){value=127-zt2;smoothandsend();} break; case P: switch(j){ case 1: value=pt1; smoothandsend(); break; case 2: value=pt2; smoothandsend(); break; case 3: value=pt3; smoothandsend(); break; case 4: value=pt4; smoothandsend(); break; } break; case S: if (j==15) { //buf15- trigger if (!sustped[contch[contp]] && b15minusdown) { //down trig b15minusdown = 0; sustped[contch[contp]] = 1; control_change(contch[contp], contno[contp], 127); } if (sustped[contch[contp]] && b15minusup) { //up trig b15minusup=0; sustped[contch[contp]]=0; control_change(contch[contp], contno[contp],0); } } break; } } ////////////////////////////// // // smoothandsend -- // void smoothandsend(void) { pvalue = contval[contp]; value -= contbalance[contp]; if (value < 1) { value = 1.0; } if (value > 127.0) { value = 127.0; } contval[contp] = pvalue + (value-pvalue)*SMOOTHING; invalue = (short)contval[contp]; ipvalue = (short)pvalue; if(invalue != ipvalue) { //printf("nvalue,pvalue= %f %f\n",contval[contp],pvalue); control_change(contch[contp]+1, contno[contp], invalue); } } ////////////////////////////// // // playrecord -- execute a score record -- for example starting a note. // It is called and is executed at the real-time moment that the note is // suppose to be played. it looks at the record stored in scorkd[]. it // looks at the op code of the record and does a switch depending on // the op code to different blocks of code which handle the different // op codes. void playrecord(void) { int i; int c; int v; int keyno; int keyvel; int beg; int end; int accent; int keyvela; int tp; c = scorkd[0]; switch (c) { case NOTE: // turns on a note or a chord // printf("note= %d %d %d %d %d",scorkd[0],scorkd[1],scorkd[2], // scorkd[3],scorkd[4]); v = scorkd[2]; c = channel[v]; beg = chordpi[v]; end = chordp[v]; keyvel = keyvelfun(v); for (i=beg; i 127) { keyvela = 127; } //printf("%d %d %d\n",c,keyno,keyvela); note_on(NOTECONTROL,keyno,keyvela); chord[beg++] = keyno; } chordp[v]=beg; } break; case TRIG: // record produced by a "/" in score break; case REST: // turns off all notes playing in a given voice v = scorkd[2]; c = channel[v]; beg = chordpi[v]; end = chordp[v]; for (i=beg; i127) { keyvela = 127; } note_on(NOTECONTROL, keyno, keyvela); break; case MNOTEOFF: // turns off a single note v=scorkd[2];c=channel[v];keyno=scorkd[3];accent=scorkd[4]; keyvel=keyvelfun(v); keyvela=accent+keyvel; if(keyvela<1)keyvela=1;if(keyvela>127)keyvela=127; note_on(NOTECONTROL,keyno,0); break; case MEASURE: //print measure number, stop scan cout << "measure= " << measure++ << " \r"; if (measure > startmeasure) { scan=0; } break; case PITCHBEND: v = scorkd[2]; c = channel[v]; synth.pw(c, scorkd[3], scorkd[4]); break; case PEDAL: // "p" in score turns sustain pedal on v = scorkd[2]; c = channel[v]; control_change(c, 64, 127); break; case UPPEDAL: // "P" in score turns sustain pedal off v = scorkd[2]; c = channel[v]; control_change(c,64,0); break; case CONTTEMPO: // "w"--continuous tempo control with y1, ignore beats if (ctempo) { ctempo = 0; vtemp = 0; } else { ctempo = 1; vtemp = 1; } break; case FTEMP: // "W"--fixed tempo control, ignore beats if (ctempo) { ctempo=0; vtemp=0; } else { ctempo=1; vtemp=0; } break; case PROGRAMCHANGE: // "t" in score will cause a midi program change v = scorkd[2]; c = channel[v]; program_change(c+1, scorkd[3]); break; case SETCHANNEL: // the midi channel for a given voice is kept in // channel[]. it is set with an "h" in the score channel[scorkd[2]] = scorkd[3]; break; case TEMPO: // "v"--set a fixed tempo starting at next event tempo = temposave = (scorkd[2]+(scorkd[3]<<6))>>2; temposet=1; break; case KEYVELOCITY: // "k"--setup keyvelocity control dynamic[scorkd[2]] = scorkd[3]; dyntype[scorkd[2]] = scorkd[4]; break; case BATON2: // T in score turna baton 2 on or off as a source of beats if (baton2) { baton2 = 0; } else { baton2 = 1; } break; case MARK: //rehersal mark--displayed during performance mark = scorkd[3]; break; case DOTEQUALS: // change ratio of dot to comma tempo = ((int)tempo*scorkd[3])/scorkd[4]; dotchange = 1; dotro = scorkd[3]; dotrn = scorkd[4]; break; case CONTCONTROL: // setup patchcord for continuous control if (scorkd[6] == V) { // if control change is a constant, send only once: tp = scorkd[7] - scorkd[8]; if (tp < 0) { tp = 0; } control_change(scorkd[5]+1, scorkd[4], tp); } else { // if control change is baton position, setup patchchord contpatch = scorkd[3]; contno[contpatch] = scorkd[4]; contch[contpatch] = scorkd[5]; controlerfn[contpatch] = scorkd[6]; controlerfnv[contpatch] = scorkd[7]; contbalance[contpatch] = scorkd[8]; } break; case INIT: //initialization for (i=1; i<17; i++) { channel[i]=i-1; } tempo = temposave = temposet = 1; ctempo = vtemp = 0; break; case NOACTION: break; } } ////////////////////////////// // // keyvelfun -- keyvelocity control, v is voice int keyvelfun(int v) { int type; int keyvel = 0; type=dyntype[v]; switch(type){ case X: if (dynamic[v] == 1) { keyvel=xt1; } else { keyvel=xt2; } break; case Y: if (dynamic[v] == 1) { keyvel=yt1; } else { keyvel=yt2; } break; case Z: if (dynamic[v] == 1) { keyvel=zt1; } else { keyvel=zt2; } break; case P: if (dynamic[v]<4) { //pots 1-3 keyvel = buf[10+dynamic[v]]>>5; } else { // pot 4 keyvel=buf[5]; } break; case V: keyvel = dynamic[v]; break; } return keyvel; } ////////////////////////////// // // getnextchar -- // int getnextchar(void) { int nextchar; nextchar = getc(fp2); if (nextchar==EOF) { playmode = 0; cout << "END OF SCORE" << endl; pcc(); } return nextchar; } ////////////////////////////// // // readscorez -- // void readscorez(void) { int iii; int opcode; if (fp2==NULL || !playmode) { return; } nextbeat=0; nextrecord: charcount = getnextchar(); if (!playmode) { return; } opcode = getnextchar(); if (!playmode) { return; } nextbeat += getnextchar(); if (!playmode) { return; } if (opcode == NOOP) { goto nextrecord; } scorkd[0] = opcode; scorkd[1] = nextbeat; scorkdend = charcount-1; if (charcount > 3) { for (iii=2; iii