//cond.cpp--conductor program--float tempo--100ms retrigger time
// Converted to linux Wed Dec 20 19:10:35 PST 2000, by Craig Sapp
// $Smake: g++ -O6 -DLINUX -DALSA -I/user/c/craig/hciimprov/include -o %b %f %
// -lpthread -L/home/mvm/cp1/hci/condtest/lib -limprov -lasound
#include <stdio.h>
#ifndef OLDCPP
#include <iostream>
using namespace std;
#else
#include <iostream.h>
#endif
// #include <conio.h> /* doesn't exist in linux */
#include "batonImprov.h"
void pitch_wheel(int a, int b, int c);
void command(int a, int b);
//////////////////////////////////////////////////////////////////////////
//#include "cond.h"
// cond.h for dos newbat
#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],abeatset,arg1,arg2;
long beatsum;
long beat_time;
short b[28],baton2,bufchan;
unsigned char bufp;
short b1,b2;
unsigned char calf[2048];
short chan;
short channel[VOICES];
short chord[VOICES*CHORDSIZE];
short chordpi[VOICES],chordp[VOICES];
short controler;
short cont4,contp,ctempo,contpatch;
short contch[NOCONTROL],contno[NOCONTROL];/* arrays defining patchcords */
short controlerfn[NOCONTROL],controlerfnv[NOCONTROL];
int xform[NOCONTROL];
float xforma[NOCONTROL],xformb[NOCONTROL];
float tx0,tx1,ty0,ty1;
//short contbalance[NOCONTROL];
short sustped[16];
long contime;
short dataa,dist;
short dotchange,dotro,dotrn;
short diff[11];
short dx,dr0,drumset1,drumset2;
short dynamic[VOICES],dyntype[VOICES];
long dur;
short endscoreflag;
// extern short hit1,hit2;short hungnote,hungnoteno;
long ibeat,itim;
short interval;
short kk;
short keych,keyno,keyvel;
long keytime;
short mark,midich,midichar,minus14,minus15,mm;
unsigned char midibuf[256],midirbuf[256];
unsigned char midipi,midipo,midirpi,midirpo;
short num,nextkeyno,noteon,nextbeat,nobat,needscore;
short notenumb1,notenumb2,noteon1,noteon2;
long nexttime,nextnotetime;
short zpause,plus14,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;
// extern short set1,set2;short stick,st0,st1,st2,set12p,sticklevelflag;
short& set1 = baton.calib[1];
short sum,suminc,range;
short t[28],temposet,thru;
long threshtime;
short tranftype;
extern long t_time;long t_times,t_tdata,t_tkey;
short volume[16],vtemp,volumeconst,volx;
int value;
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],scorepf[100];
// these variables were removed from "extern"
char scoref[1000];
int argcglobal;
short newdotp,scoresok;
//
// end of cond.h
//
//////////////////////////////////////////////////////////////////////////
int temp1,temp2,playmode;
short sysexmessage,midich1,maxscore,minscore,sendingscore,timecount;
unsigned char midi_port;
unsigned char midififo[256];
unsigned int midiip,midiop,midiipsav;
short midimessages,sysexcase,scorechars,charcount,endplayscoreflag;
unsigned int scoreip,scoreop;
long controlchangetime,lastwhacktime;
int startmeasure;
int scan,discard;
int measure;
int readscore;
int ii;
FILE *fp2;
short buf[17];
int b14minusdown;
int b14minusup;
int b15minusdown;
int b15minusup;
float tempo,temposave;
//functions
int keyvelfun(int);
int getch(void);
void xformandsend(void);
void pcc(void);
void loadplay(void);
void playrecord(void);
void readscorez(void);
void stkcontrol(void);
/*--------------------beginning improvization algorithms------------------*/
/*---------------------initialization algorithms--------------------------*/
void description(void){
printf
("CONDUCTOR COMMANDS s--select score z--start playing\n");
printf
(" S--silence synth n--toggle no baton mode on/off\n");
}//end description()
void initialization(void){
printf("CONDUCTOR COMMANDS s--select score z--play n--no baton mode on/off\n");
argcglobal = options.getArgCount() + 1;
const char* scorefx;
if (argcglobal >= 2) {
scorefx = options.getArg(1);
} else {
scorefx = "\0";
}
strcpy(scoref, scorefx);
if(argcglobal==2){
printf("score file is %s \n", scoref);
ii=-1;while(scoref[++ii]!='\0')scorepf[ii]=scoref[ii];
scorepf[ii++]='.';scorepf[ii++]='p'; scorepf[ii]='\0';
ii=-1;while(scoref[++ii]!='\0')midif[ii]=scoref[ii];
midif[ii++]='.';midif[ii++]='m';midif[ii++]='i';
midif[ii++]='d';midif[ii]='\0';
if((fp2=fopen(scorepf,"r+b")) != NULL){
newdotp=0;
printf("type COMMAND (type z to start playing)\n");
}
else{printf("SCORE NOT FOUND\n");}
}
startmeasure=1;
}
void initializecond(void){
int i;
//whackint1=0;
sysexcase=midiip=midiop=midimessages=0;
for(i=0;i<VOICES;i++)chordpi[i]=chordp[i]=CHORDSIZE*i;
tempo=temposave=temposet=1;scan=ctempo=vtemp=zpause=0;
whack1=whack2=b14minusdown=b14minusup=b15minusdown=b15minusup=0;
scan=0;measure=1;/*if(startmeasure!=1)*/scan=1;
endscoreflag=0;
scoreop=scoreip=scoreadp=needscore=scorestate=scorechars=0;
endplayscoreflag=0;
threshtime=nexttime=pt_time=pt_beat=controlchangetime=t_time;
nexttime=0;
readscorez();
playmode=1;
}//end initializecond()
/*--------------------main loop algorithms -------------------------------*/
void mainloopalgorithms(void){
if(playmode){
while(scan){ //jump to next measure
if(scorkd[0]==NOTE)goto readsk;
if(scorkd[0]==MNOTEON)goto readsk; //skip midi note on's
if(scorkd[0]==MNOTEOFF)goto readsk; //skip midi note on's
if(scorkd[0]==REST)goto readsk; //skip midi note on's
playrecord(); //play score record
readsk:if(playmode)readscorez(); //read next score record
}
if(t_time>controlchangetime){ // if midibuf[] is empty send control 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=(float)(((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);
}
}
}//end if(!whack1)
}
}
endmainloop:;
} //end if(playmode
}
/*--------------------triggered algorithms--------------------------------*/
void stick1trig(void){}
void stick2trig(void){}
void b14plustrig(void){
// clmidi();offmidi();t_sched_off();t_stop();exit(0);
}
void b15plustrig(void){printf("b15+ trigger\n");}
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 's': //select score
echoKeysOn();
printf("type name of score file \n"); getch();scanf("%s",scoref);
echoKeysOff();
ii=-1;while(scoref[++ii]!='\0')scorepf[ii]=scoref[ii];
scorepf[ii++]='.';scorepf[ii++]='p'; scorepf[ii]='\0';
ii=-1;while(scoref[++ii]!='\0')midif[ii]=scoref[ii];
midif[ii++]='.';midif[ii++]='m';midif[ii++]='i';
midif[ii++]='d';midif[ii]='\0';
if((fp2=fopen(scorepf,"r+b")) != NULL){
newdotp=0;
printf("type COMMAND (type z to start playing)\n");
}
else{printf("SCORE NOT FOUND\n");}
break;
case 'z':
command(17,127); //turn on position reporting
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
echoKeysOn();
printf("startmeasure =");getch();scanf("%d",&startmeasure);
echoKeysOff();
break;
default: printf("UNKNOWN COMMAND \n");pcc();break;
}//end switch(testch)
}//end keyboardchar(testch)
void finishup(void) { }
void loadplay(void){
int ii;
//long nexttime;
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){
printf("PLAY SCORE %s \n", scoref);
initializecond();
}
else{printf("SCORE.P FILE NOT FOUND\ntype COMMAND\n"); scoresok=0; }
}//end loadplay()
void stkcontrol(void) // coupling batons to control changes
{
int i,j;
value=-1;
i=controlerfn[contp];
j=controlerfnv[contp];
switch(i){
case X:if(j==1 ){value=xt1;xformandsend();}
if(j==2 ){value=xt2;xformandsend();}
break;
case Y:if(j==1 ){value=yt1;xformandsend();}
if(j==2 ){value=yt2;xformandsend();}
break;
case Z:if(j==1){value=zt1;xformandsend();}
if(j==2){value=zt2;xformandsend();}
break;
case P:switch(j){
case 1:control_change(contch[contp]+1,contno[contp],pt1);break;
case 2:control_change(contch[contp]+1,contno[contp],pt2);break;
case 3:control_change(contch[contp]+1,contno[contp],pt3);break;
case 4:control_change(contch[contp]+1,contno[contp],pt4);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;
}
}
void xformandsend(void){
float xformvalue;
if(xform[contp]==0){control_change(contch[contp]+1,contno[contp],value);}
else{
xformvalue=xformb[contp]+(xforma[contp]*(float)value);
value=(int)xformvalue;if(value<0)value=0;if(value>127)value=127;
control_change(contch[contp]+1,contno[contp],value);
}
}
// play--------------------execute a score record------------------------
/* play executes a score record--for example starting a note. itis 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,c,v,keyno,keyvel,beg,end,accent,keyvela,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<end;i++)note_on(c+1,chord[i],0);/*turns off notes that are playing */
i=3;
while(i<scorkdend){ /* turns on new note or notes */
keyno=scorkd[i++];
keyvela=scorkd[i++]+keyvel;
if(keyvela<1)keyvela=1;if(keyvela>127)keyvela=127;
//printf("%d %d %d\n",c,keyno,keyvela);
note_on(c+1,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;i<end;i++)note_on(c+1,chord[i],0);
chordp[v]=beg;
break;
keyvel=keyvelfun(v);
case MNOTEON: /*turns on a single note. note must be ended with a subsequent MNOTEOFF record*/
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(c+1,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(c+1,keyno,0);
break;
case MEASURE: //print measure number, stop scan
cout << "measure= " << measure << "\r" << flush;
measure++;
if(measure>startmeasure)scan=0;
break;
case PITCHBEND:
v=scorkd[2];c=channel[v];
pitch_wheel(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, ignor beats */
if(ctempo){ctempo=0;vtemp=0;}else{ctempo=1;vtemp=1;}
break;
case FTEMP: /* "W"--fixed tempo control, ignor 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=(float)((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=(float)(((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];
if(scorkd[8]==scorkd[9]){xform[contpatch]=0;}
else{
tx0=(float)scorkd[8];tx1=(float)scorkd[9];ty0=(float)scorkd[10];ty1=(float)scorkd[11];
xform[contpatch]=1;
xforma[contpatch]= (ty1-ty0)/(tx1-tx0);
xformb[contpatch]= ((tx1*ty0)-(tx0*ty1))/(tx1-tx0);
//printf("xform,contpatch= %d %d \n",xform[contpatch],contpatch);
}
}
break;
case INIT: //initialization
for(i=1;i<17;i++)channel[i]=i-1; //default channel#=voice#
tempo=temposave=temposet=1;ctempo=vtemp=0;
break;
case NOACTION:
break;
} // end switch(c)
} // playrecord()
keyvelfun(int v) // keyvelocity control, v is voice
{
int type,keyvel;
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){keyvel=buf[10+dynamic[v]]>>5;} //pots 1-3
else{keyvel=buf[5];} //pot 4
break;
case V:keyvel=dynamic[v];break;
}
return(keyvel);
}
getnextchar(){
int nextchar;
nextchar=getc(fp2);
if(nextchar==EOF){playmode=0;printf("END OF SCORE\n");pcc();}
return(nextchar);
}
void readscorez(void){
int iii,opcode;
if(fp2==NULL || !playmode) return; // return(0);
nextbeat=0;
nextrecord:
charcount=getnextchar();if(!playmode)return; //return(0);
opcode=getnextchar();if(!playmode)return; //return(0);
nextbeat+=getnextchar();if(!playmode)return; //return(0);
if(opcode==NOOP)goto nextrecord;
scorkd[0]=opcode;
scorkd[1]=nextbeat;
scorkdend=charcount-1;
if(charcount>3){
for(iii=2;iii<scorkdend;iii++){
scorkd[iii]=getnextchar();if(!playmode)return; //return(0);
}
}
scorkd[scorkdend]=0;
//printf("scorkd= %d %d %d %d %d %d %d %d \n",scorkd[0],scorkd[1],scorkd[2],scorkd[3],scorkd[4],scorkd[5],scorkd[6],scorkd[7]);
beatsum+=nextbeat;
// return(0);
}//end readscore()
void pcc(void){
printf (
"type NEXT COMMAND (type Q to quit, type ? to print list of commands)\n");
}
/////////////////////////////////////////////////////////////////////////////////////
//
// added functions:
//
void command(int a, int b) {
synth.send(0xa0, a, b);
}
void pitch_wheel(int a, int b, int c) {
synth.send(0xe0 | a, b, c);
}
#ifndef VISUAL
int getch(void) { }
#endif
// md5sum: 67cc02b5b82cf04dbe79d6708ee2976b cond.cpp [20050403]