| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270 |
- /*
- * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
- * http://www.trevorwishart.co.uk
- * http://www.composersdesktop.com
- *
- This file is part of the CDP System.
- The CDP System is free software; you can redistribute it
- and/or modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The CDP System is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the CDP System; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
- *
- */
- /* columns */
- #include <columns.h>
- #define CALCLIM 0.001
- #define M 7
- #define NSTACK 50
- #define MIDDLE_C_MIDI_OCTAVE 5
- #define CONVERT_LOG10_TO_LOG2 (double)3.321928
- #define LOW_A 6.875 /* Frequency of A below MIDI 0 */
- double cntevents(double,double,double);
- int samesize(double,double,double,double,double);
- void approxtimes(double,double,int);
- void getetime(double,double,double,double,int);
- double gethibnd(double,double,double,double,double);
- double getlobnd(double,double,double,double,double);
- double refinesize(double,double,double,double,double,double);
- void prnt_pitchclass(int,int);
- int strgetfloat_db(char **,double *);
- static void bublsort(void);
- static void test_warp_data(void);
- int *cntr;
- char **strings = 0;
- char *stringstore;
- int stringscnt = 0;
- int stringstoresize = 0, stringstart = 0;
- /************************ TIMEVENTS ******************************
- *
- * Generates event positions from startsize and end size
- *
- * Let start-time be T0 and end time be T1
- * Let start size be S0 and end S1
- *
- * number of event is given by :-
- *
- * N = (T1-T0) log S1
- * ------- e__
- * (S1-S0) S0
- *
- * In general this will be non-integral, and we should
- * round N to an integer, and recalculate S1 by successive
- * approximation.
- *
- * Then positions of events are given by
- *
- * for X = 0 to N (S1-S0)
- * ----- X
- * T = (S1T0 - S0T1) S0(T1 - T0) (T1-T0)
- * s ----------- + ---------- e
- * (S1 - S0) (S1 - S0)
- *
- * If difference in eventsizes input to the main program is very small
- * then infinite values result. To avoid this we divert the calculation
- * to another routine (which assumes the input values are equal.
- * The value of CALCLIM = 0.001. (LArger than usual i.e. 0.05)
- *
- * If size values are so BIG that they exceed segment duration,
- * eventsize becomes segment duration and a Warning is printed.
- *(1) events approx same size.
- *(2) events of different sizes, find the number of events which approx
- * fit in the duration.
- *(3) If there's only one event .. that's it.
- *(4) Note the error (difference between approximated whole number of events
- * and the actual,non-integer, number of events).
- *(5) Calculate acceptable bounds on a new endeventsize, which will give
- * a better fit of the integer number of events within the given duration.
- *(6) Find an acceptable final value for endeventsize by successive approx
- * NB we don't know whether the function increases as d increases
- * so lobound may be > hibound. However, the maths of the method will
- * still work, just inverting the sense of the search!!
- *(7) Calculate the inital times of the events.
- *
- * This function returns the number of events within the time-interval,
- * and returns the times of these events in the array-of-doubles pos.
- */
- int timevents(double intime0,double intime1,double insize0,double insize1)
- {
- int number;
- double fnum, fnumber, error;
- double lobound, hibound, duration;
- if(flteq(insize0,0.0) || flteq(insize1,0.0)) {
- sprintf(errstr,"Event size of zero encountered.\n");
- do_error();
- }
- duration = (intime1-intime0);
- if(duration<=0.0) {
- sprintf(errstr,"Inconsistent input times (2nd before 1st).\n");
- do_error();
- }
- if(fabs(insize1-insize0)<CALCLIM) /* 1 */
- return(number = samesize(intime0,intime1,insize0,insize1,duration));
- fnum = cntevents(duration,insize0,insize1); /* 2 */
- number = round(fnum);
- if(number<=1) /* 3 */
- return(1);
- pos = (double *)exmalloc((number+1) * sizeof(double));
- fnumber = (double)(number); /* 4 */
- error = fabs(fnum - fnumber);
- lobound = insize1; /* 5 */
- hibound = insize1;
- if(fnum<fnumber)
- hibound = gethibnd(fnum,fnumber,insize1,insize0,duration);
- if(fnum>fnumber)
- lobound = getlobnd(fnum,fnumber,insize1,insize0,duration);
- if(error > FLTERR) { /* 6 */
- if(lobound < hibound) /* LOBOUND is a HIGH SIZE for a LOW COUNT!! */
- swap(&hibound,&lobound);
- insize1 = refinesize(hibound,lobound,fnumber,error,duration,insize0);
- } else {
- insize1 = (hibound+lobound)/2;
- } /* 7 */
- getetime(intime0,intime1,insize0,insize1,number);
- pos[number] = intime1;
- return(number+1);
- }
- /*************************** CNTEVENTS *****************************/
- double cntevents(double dur,double s0,double s1)
- { double f1,f2;
- f1 = dur;
- f2 = s1-s0;
- f1 /= f2;
- f2 = s1/s0;
- f2 = log(f2);
- f1 *= f2;
- return(fabs(f1));
- }
- /******************************* SAMESIZE *******************************
- *
- * get event positions, if eventsize approx same throughout segment.
- *
- *(1) Get average size, find number of events and round to nearest int.
- *(3) Recalculate size, and thence event times.
- */
- int samesize
- (double intime0,double intime1,double insize0,double insize1,double duration)
- {
- int number;
- double fnum, size; /* 1 */
- size = (insize0+insize1)/2;
- fnum = duration/size;
- number = round(fnum);
- size = duration/(double)(number);
- pos = (double *)exmalloc((number+1) * sizeof(double));
- approxtimes(intime0,size,number);
- pos[number] = intime1;
- return(number+1);
- }
- /************************ APPROXTIME ***************************
- *
- * Calculate time-positions of equally spaced events.
- */
- void approxtimes(double intime0,double size,int number)
- { int k;
- double *q = pos;
- *q++ = intime0;
- for(k=1;k<number;k++) {
- *q = *(q-1) + size;
- q++;
- }
- }
- /******************************* GETETIME ********************************
- *
- * Calculate time-positions of events that vary in size between s0 and s1.
- */
- void getetime(double t0,double t1,double s0,double s1,int number)
- { int n;
- double sdiff = s1-s0, tdiff = t1-t0, d1, d2, d3, *q = pos;
- *q++ = t0;
- for(n=1;n<number;n++) {
- d1 = sdiff/tdiff;
- d1 *= (double)n;
- d1 = exp(d1);
- d2 = s0*tdiff;
- d2 /= sdiff;
- d1 *= d2;
- d2 = s1*t0;
- d3 = s0*t1;
- d2 -= d3;
- d2 /= sdiff;
- d1 += d2;
- *q++ = d1;
- }
- }
- /****************************** GETHIBND *****************************
- *
- * Find SMALLER VALUE of SIZE, to GIVE a LARGER VALUE of NO-OF-SEGS
- * which will act as an UPPER BOUND to be used for searching
- * for an endsize that will give the integer number of events in the duration,
- *
- * (0) Start by REDUCING size, to give BIGGER fnum.
- *(1) If we're going downwards, (try -ve) and we go below zero,restore value
- * and subtract less.
- *(2) If the fnums are moving in the opposite direction to what we expect,
- * restore values and increment in the opposite direction,but only half
- * as much!
- */
- double gethibnd(double fnum,double fnumber,double insize1,
- double insize0,double duration)
- { double lastfnum, try = -1.0; /* 0 */
- double bound = insize1;
- while(fnum<fnumber) {
- lastfnum = fnum;
- bound += try;
- while(bound<=0) { /* 1 */
- bound -= try;
- try /= 2.0;
- bound += try;
- }
- fnum = cntevents(duration,insize0,bound);
- if(fnum<lastfnum) { /* 2 */
- fnum=lastfnum;
- bound -= try;
- try = -(try/2.0);
- }
- }
- return(bound);
- }
- /****************************** GETLOBND *****************************
- *
- *
- * Find LARGER VALUE of SIZE, to GIVE a SMALLER VALUE of NO-OF-SEGS
- * which will act as a LOWER BOUND to be used for searching
- * for an endsize that will give the integer number of events in the duration,
- *
- * LOBOUND is a LARGER value of SIZE to give SMALLER value of NUM-OF-SEGS.
- *
- * (0) Start by INCREASING size, to give SMALLER fnum.
- * (1) If we're going downwards, (try -ve) and we go below zero, restore
- * propr value of bound, value and subtract less.
- * (2) If the fnums are moving in the opposite direction to what we expect,
- * (fnum > lastfnum, while we're trying to DECREASE fnum)
- * restore values and increment in the opposite direction,but only half
- * as much!
- */
- double getlobnd(double fnum,double fnumber,double insize1,
- double insize0,double duration)
- { double try = 1.0;
- double lastfnum;
- double bound = insize1;
- while(fnum>fnumber) {
- lastfnum = fnum;
- bound += try;
- while(bound<=0) {
- bound -= try;
- try /= 2;
- bound += try;
- }
- fnum = cntevents(duration,insize0,bound);
- if(fnum>lastfnum) {
- fnum =lastfnum;
- bound -= try;
- try = -(try/2);
- }
- }
- return(bound);
- }
- /***************************** REFINESIZE ******************************
- *
- * refine size of final event to reduce error within bounds.
- */
- double refinesize(double hibound,double lobound,double fnumber,
- double error,double duration,double insize0)
- { double size = (hibound+lobound)/2, fnum;
- while(error>(FLTERR)) {
- size = (hibound+lobound)/2;
- fnum = cntevents(duration,insize0,size);
- error = fabs(fnumber-fnum);
- if(error>FLTERR) {
- if(fnum<fnumber)
- lobound = size;
- else
- hibound = size;
- }
- }
- return(size);
- }
- /**************************STRGETFLOAT **************************
- * takes a pointer TO A POINTER to a string. If it succeeds in finding
- * a float it returns the float value (*val), and it's new position in the
- * string (*str).
- */
- int strgetfloat(char **str,double *val)
- { char *p, *q, *end;
- double numero;
- int point, valid;
- for(;;) {
- point = 0;
- p = *str;
- while(isspace(*p))
- p++;
- q = p;
- if(!isdigit(*p) && *p != '.' && *p!='-')
- return(0);
- if(*p == '.'|| *p == '-') {
- if(*p == '-') {
- p++;
- } else {
- point++;
- p++;
- }
- }
- for(;;) {
- if(*p == '.') {
- if(point)
- return(0);
- else {
- point++;
- p++;
- continue;
- }
- }
- if(isdigit(*p)) {
- p++;
- continue;
- } else {
- if(!isspace(*p) && *p!=ENDOFSTR)
- return(0);
- else {
- end = p;
- p = q;
- valid = 0;
- while(p!=end) {
- if(isdigit(*p))
- valid++;
- p++;
- }
- if(valid) {
- if(sscanf(q,"%lf",&numero)!=1)
- return(0);
- *val = numero;
- *str = end;
- return(1);
- }
- return(0);
- }
- }
- }
- }
- return(0); /* NOTREACHED */
- }
- /**************************STRGETFLOAT_DB **************************
- * takes a pointer TO A POINTER to a string. If it succeeds in finding
- * a float it returns the float value (*val), and it's new position in the
- * string (*str). IT JUMPS OVER 'db'
- */
- int strgetfloat_db(char **str,double *val)
- {
- char *p, *q, *end;
- double numero;
- int point, valid;
- for(;;) {
- point = 0;
- p = *str;
- while(isspace(*p))
- p++;
- q = p;
- if(!isdigit(*p) && *p != '.' && *p!='-')
- return(0);
- if(*p == '.'|| *p == '-') {
- if(*p == '-') {
- p++;
- } else {
- point++;
- p++;
- }
- }
- for(;;) {
- if(*p == '.') {
- if(point)
- return(0);
- else {
- point++;
- p++;
- continue;
- }
- }
- if(isdigit(*p)) {
- p++;
- continue;
- } else {
- if(!isspace(*p) && *p!=ENDOFSTR && !(*p=='d' || *p=='D') && !(*(p+1)!='b' || *(p+1)!='B'))
- return(0);
- else {
- end = p;
- p = q;
- valid = 0;
- while(p!=end) {
- if(isdigit(*p))
- valid++;
- p++;
- }
- if(*end=='d' || *end=='D')
- end += 2;
- if(valid) {
- if(sscanf(q,"%lf",&numero)!=1)
- return(0);
- *val = numero;
- *str = end;
- return(1);
- }
- return(0);
- }
- }
- }
- }
- return(0); /* NOTREACHED */
- }
- /**************************STRGETSTR ***************************/
- int strgetstr(char **str,char *str2)
- {
- char *p, *q, c;
- p = *str;
- while(isspace(*p))
- p++;
- if(*p == ENDOFSTR)
- return(0);
- q = p;
- while(!isspace(*p))
- p++;
- c = *p;
- *p = ENDOFSTR;
- strcpy(str2,q);
- *p = c;
- *str = p;
- return(1);
- }
- /************************** HZTOMIDI ************************/
- double miditohz(double midi)
- { double frq;
- frq = midi;
- frq += 3.0;
- frq /= 12.0;
- frq = pow((double)2,frq);
- frq *= LOW_A;
- return(frq);
- }
- /****************************** MIDITOHZ *************************/
- double hztomidi(double hz)
- { double midi;
- midi = hz;
- midi /= LOW_A;
- midi = log10(midi) * CONVERT_LOG10_TO_LOG2;
- midi *= 12.0;
- midi -= 3.0;
- return(midi);
- }
- /*********************** RNDPERM ************************/
- void rndperm(double *z)
- {
- int n,t;
- int k = cnt * sizeof(double);
- permm = (double *)exmalloc(k*2);
- memset((char *)permm,0,k*2);
- permmm = permm + cnt;
- for(n=0;n<cnt;n++) {
- t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
- if(t==n)
- prefix(z,n);
- else
- insert(z,n,t);
- }
- memcpy((char *)z,(char *)permmm,k);
- free(permm);
- }
- /*********************** RNDPERM2 ************************
- *
- * Does not malloc and free perm internally.
- */
- void rndperm2(double *z)
- { int n,t;
- int k = cnt * sizeof(double);
- memset((char *)permm,0,k*2);
- permmm = permm + cnt;
- for(n=0;n<cnt;n++) {
- t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
- if(t==n)
- prefix(z,n);
- else
- insert(z,n,t);
- }
- memcpy((char *)z,(char *)permmm,k);
- }
- /*********************** MULTRNDPERM ************************
- * START
- * orig orig orig
- * |--------|--------|--------|
- * 1ST PERM
- * perm1 orig orig
- * |--------|--------|--------|
- * NEXT PERM
- * perm1 perm2 orig
- * |--------|--------|--------|
- * MEMCPY
- * perm1=perm2 orig orig
- * |--------|--------|--------|
- * go to NEXT PERM
- */
- void multrndperm(double *blok1)
- { int n, m;
- double lastenditem, *blok2, *blok3;
- int oneblok = cnt * sizeof(double);
- int twobloks = oneblok*2;
- int threebloks = oneblok*3;
- blok1 = (double *)exrealloc((char *)blok1,threebloks);
- blok2 = blok1 + cnt;
- blok3 = blok2 + cnt;
- memcpy((char *)blok2,(char *)blok1,oneblok);
- memcpy((char *)blok3,(char *)blok1,oneblok);
- permm = (double *)exmalloc(cnt * 2 * sizeof(double));
- rndperm2(blok1); /* perm 1st copy */
- for(n=0;n<cnt;n++)
- do_valout(blok1[n]);
- for(m=1;m<ifactor;m++) { /* now do perms on 2nd copy */
- lastenditem = *(blok2-1);
- do {
- rndperm2(blok2);
- } while(blok2[0]==lastenditem);
- /* Avoid element repeat at block boundaries */
- for(n=0;n<cnt;n++)
- do_valout(blok2[n]);
- memcpy((char *)blok1,(char *)blok2,twobloks);
- /* Move perm along & restore orig set */
- }
- fflush(stdout);
- free(permm);
- }
- /************************** INSERT *************************/
- void insert(double *z,int m,int t)
- {
- shuffle(t+1,m);
- permmm[t+1] = z[m];
- }
- /************************** PREFIX ***************************/
- void prefix(double *z,int m)
- { permmm--;
- permmm[0] = z[m];
- }
- /*************************** SHUFFLE ***********************/
- void shuffle(int k,int m)
- {
- int n;
- double *i;
- if(k/2 > m) { /* shuffle up */
- i = &permmm[m];
- for(n=m;n>k;n--) {
- *i = *(i-1);
- i--;
- }
- } else { /* shuffle down */
- i = &permmm[0];
- for(n=0;n<k;n++) {
- *(i-1) = *i;
- i++;
- }
- permmm--; /* Move base of perm down by 1 */
- }
- }
- /******************************** EXMALLOC ****************************/
- char *exmalloc(int n)
- {
- char *p;
- if((p = (char *)malloc(n))==NULL) {
- sprintf(errstr,"ERROR: Memory allocation failed\n");
- do_error();
- }
- return(p);
- }
- /************************ READ_INPUT_FILE ****************************/
- void read_input_file(FILE *fpp)
- { char *p;
- double *number2;
- while(fgets(temp,20000,fpp)!=NULL) {
- p = temp;
- while(strgetfloat(&p,&number[cnt])) {
- if(++cnt >= arraysize) {
- arraysize += BIGARRAY;
- /* NOVEMBER 2001 NEW */
- number2 = (double *)malloc(arraysize*sizeof(double));
- memcpy((void *)number2,(void *)number,cnt * sizeof(double));
- number = number2;
- /* NOVEMBER 2001 OLD
- number = (double *)exrealloc((char *)number,arraysize*sizeof(double));
- */
- }
- }
- }
- }
- /************************* DO_INFILE ***************************/
- void do_infile(char *argv)
- {
- char *p;
- double *number2;
- if((fp[0] = fopen(argv,"r"))==NULL) {
- sprintf(errstr,"Cannot open infile %s\n",argv);
- do_error();
- }
- while(fgets(temp,20000,fp[0])!=NULL) {
- p = temp;
- while(strgetfloat(&p,&number[cnt])) {
- if(++cnt >= arraysize) {
- arraysize += BIGARRAY;
- /* NOVEMBER 2001 NEW */
- if((number2=(double *)malloc(arraysize*sizeof(double)))==NULL) {
- sprintf(errstr,"Out of memory for more numbers at %d numbers\n",cnt);
- do_error();
- }
- memcpy((void *)number2,(void *)number,cnt * sizeof(double));
- number = number2;
- /* NOVEMBER 2001 OLD
- if((number=(double *)exrealloc((char *)number,arraysize*sizeof(double)))==NULL) {
- sprintf(errstr,"Out of memory for more numbers at %d numbers\n",cnt);
- do_error();
- }
- */
- }
- }
- }
- if(cnt <=0) {
- sprintf(errstr,"Invalid or missing data.\n");
- do_error();
- }
- fclose(fp[0]);
- }
- /************************* DO_DB_INFILE ***************************/
- void do_DB_infile(char *argv)
- {
- char *p;
- if((fp[0] = fopen(argv,"r"))==NULL) {
- sprintf(errstr,"Cannot open infile %s\n",argv);
- do_error();
- }
- while(fgets(temp,20000,fp[0])!=NULL) {
- p = temp;
- while(strgetfloat_db(&p,&number[cnt])) {
- if(++cnt >= arraysize) {
- arraysize += BIGARRAY;
- number=(double *)exrealloc((char *)number,arraysize*sizeof(double));
- }
- }
- }
- if(cnt <=0) {
- sprintf(errstr,"Invalid or missing data.\n");
- do_error();
- }
- fclose(fp[0]);
- }
- /************************* DO_PITCHTEXT_INFILE ***************************/
- void do_pitchtext_infile(char *argv)
- {
- char *p;
- char temp2[200];
- if((fp[0] = fopen(argv,"r"))==NULL) {
- sprintf(errstr,"Cannot open infile %s\n",argv);
- do_error();
- }
- while(fgets(temp,200,fp[0])!=NULL) {
- p = temp;
- while(strgetstr(&p,temp2)) {
- number[cnt] = texttomidi(temp2);
- if(++cnt >= arraysize) {
- arraysize += BIGARRAY;
- number=(double *)exrealloc((char *)number,arraysize*sizeof(double));
- }
- }
- }
- if(cnt <=0) {
- sprintf(errstr,"ERROR: Invalid or missing data.\n");
- do_error();
- }
- fclose(fp[0]);
- }
- /************************* DO_OTHER_INFILE **********************/
- void do_other_infiles(char *argv[])
- {
- int n;
- if(infilecnt>2)
- fp = (FILE **)exrealloc((char *)fp,infilecnt*sizeof(FILE *));
- firstcnt = cnt;
- for(n=1;n<infilecnt;n++) {
- if((fp[n] = fopen(argv[n+1],"r"))==NULL) {
- sprintf(errstr,"\nCannot open file %s to read.\n",argv[n+1]);
- do_error();
- }
- read_input_file(fp[n]);
- if (flag == 'A' && ro =='e') {
- file_cnt[n] = cnt - firstcnt;
- firstcnt = cnt;
- } else if((flag=='J' || (flag=='C' && ro == 'c')) && cnt != firstcnt * (n+1)) {
- sprintf(errstr,"Input file %d has wrong number of values to match previous column lengths.\n",n+1);
- do_error();
- }
- }
- if (flag == 'w' && (ro == 't' || ro == 'o')) {
- test_warp_data();
- }
- }
- /********************** DO_OUTFILE *****************************/
- void do_outfile(char *argv) {
- if((fp[1] = fopen(argv,"w"))==NULL) {
- sprintf(errstr,"Cannot open file %s to write.\n",argv);
- do_error();
- exit(1);
- }
- }
- /**************************** QIKSORT ******************************/
- void qiksort(void) {
- bublsort();
- }
- /************************ BELLPERM1 ***************************/
- void bellperm1(void)
- { int n;
- for(n=0;n<cnt;n+=2)
- swap(&number[n], &number[n+1]);
- }
- /************************** BELLPERM2 ******************************/
- void bellperm2(void)
- { int n;
- for(n=2;n<cnt;n+=2)
- swap(&number[n], &number[n-1]);
- }
- /************************* BELLPERM3 ******************************/
- void bellperm3(void)
- { int n;
- for(n=2;n<cnt;n+=2)
- swap(&number[n], &number[n+1]);
- }
- /***************************** SWAP *******************************/
- void swap(double *d0,double *d1)
- {
- double temp = *d0;
- *d0 = *d1;
- *d1 = temp;
- }
- /**************************** FLTEQ *******************************/
- int flteq(double f1,double f2)
- {
- double upperbnd, lowerbnd;
- upperbnd = f2 + FLTERR;
- lowerbnd = f2 - FLTERR;
- if((f1>upperbnd) || (f1<lowerbnd))
- return(0);
- return(1);
- }
- /***************************** ELIMINATE ********************************/
- void eliminate(int m)
- {
- int n;
- for(n=m+1;n<cnt;n++)
- number[n-1] = number[n];
- cnt--;
- }
- /***************************** EXREALLOC *****************************/
- char *exrealloc(char *p,int k)
- {
- char *q;
- q = exmalloc(k);
- memcpy(q,p,k);
- free(p);
- return(q);
- }
- /****************************** TEXTTOMIDI ******************************/
- double texttomidi(char *str)
- {
- int pitch, octave, octshift = 0;
- char *p = str;
- if(!strncmp(str,"B#",2) || !strncmp(str,"b#",2))
- octshift--;
- if((str = get_pitchclass(str,&pitch,1))==(char *)0) {
- sprintf(errstr,"Unknown pitch %s\n",p);
- do_error();
- }
- if(sscanf(str,"%d",&octave)!=1) {
- sprintf(errstr,"unknown pitch-string %s or no octave value\n",p);
- do_error();
- }
- octave += (MIDDLE_C_MIDI_OCTAVE + octshift);
- pitch += (octave * 12);
- return((double)pitch);
- }
- /****************************** GET_PITCHCLASS ******************************/
- char *get_pitchclass(char *str,int *pitch,int with_octave)
- {
- switch(*str++) {
- case('c'): case('C'): *pitch = 0; break;
- case('d'): case('D'): *pitch = 2; break;
- case('e'): case('E'): *pitch = 4; break;
- case('f'): case('F'): *pitch = 5; break;
- case('g'): case('G'): *pitch = 7; break;
- case('a'): case('A'): *pitch = 9; break;
- case('b'): case('B'): *pitch = 11; break;
- default: return((char *)0);
- }
- switch(*str++) {
- case('#'): (*pitch)++; break;
- case('b'): (*pitch)--; break;
- default: str--; break;
- }
- if(with_octave) {
- if(*str==ENDOFSTR)
- return((char *)0);
- }
- return(str);
- }
- /******************************** LOGO() **********************************/
- void logo(void)
- { printf("\t ***************************************************\n");
- printf("\t * COMPOSERS DESKTOP PROJECT *\n");
- printf("\t %s $Revision: 1.8 $\n",PROG);
- printf("\t * Manipulate or Generate columns of numbers *\n");
- printf("\t * by TREVOR WISHART *\n");
- printf("\t ***************************************************\n\n");
- }
- /****************************** PITCHTOTEXT ******************************/
- void pitchtotext(int midi)
- { int oct, n;
- int basetone;
- double diff;
- for(n=0;n<cnt;n++) {
- if(midi) {
- if(number[n] < MIDIMIN || number[n] > MIDIMAX) {
- fprintf(stdout,"ERROR: MIDI value %d (%lf) is out of range for conversion to pitch.\n", n+1,number[n]);
- fflush(stdout);
- exit(1);
- }
- } else {
- if(number[n] < MIDIMINFRQ || number[n] > MIDIMAXFRQ) {
- fprintf(stdout,"ERROR: frq value %d (%lf) is out of range for conversion to pitch.\n", n+1,number[n]);
- fflush(stdout);
- exit(1);
- }
- }
- }
- for(n=0;n<cnt;n++) {
- if(!midi)
- number[n] = hztomidi(number[n]);
- oct = (int)(number[n]/12.0); /* TRUNCATE */
- oct -= 5;
- basetone = (int)floor(number[n]);
- diff = number[n] - (double)basetone;
- if(diff > .5)
- basetone++;
- prnt_pitchclass(basetone%12,oct);
- if(flteq(diff,0.0))
- strcat(errstr,"\n");
- else if(flteq(diff,0.5)) /* handle quarter tones */
- strcat(errstr,"+\n");
- else if(diff > .5)
- strcat(errstr,"(--)\n");
- else
- strcat(errstr,"(++)\n");
- fprintf(stdout,"INFO: %s",errstr);
- }
- fflush(stdout);
- }
- /****************************** PRNT_PITCHCLASS ******************************/
- void prnt_pitchclass(int z,int oct)
- {
- switch(z) {
- case(0): sprintf(errstr,"C%d",oct); break;
- case(1): sprintf(errstr,"C#%d",oct); break;
- case(2): sprintf(errstr,"D%d",oct); break;
- case(3): sprintf(errstr,"Eb%d",oct); break;
- case(4): sprintf(errstr,"E%d",oct); break;
- case(5): sprintf(errstr,"F%d",oct); break;
- case(6): sprintf(errstr,"F#%d",oct); break;
- case(7): sprintf(errstr,"G%d",oct); break;
- case(8): sprintf(errstr,"Ab%d",oct); break;
- case(9): sprintf(errstr,"A%d",oct); break;
- case(10): sprintf(errstr,"Bb%d",oct); break;
- case(11): sprintf(errstr,"B%d",oct); break;
- }
- }
- void bublsort(void) {
- int n, m;
- double temp;
- for(n=0;n<cnt-1;n++) {
- for(m = n; m<cnt; m++) {
- if(number[m] < number[n]) {
- temp = number[n];
- number[n] = number[m];
- number[m] = temp;
- }
- }
- }
- }
- /************************* DO_OTHER_STRINGLINE_INFILE ***************************/
- int do_other_stringline_infile(char *argv)
- {
- int cols;
- /*
- cnt = stringscnt; DONE PREVIOUSLY
- */
- cols = do_stringline_infile(argv,cnt);
- stringscnt -= cnt;
- return cols;
- }
- /************************* DO_STRINGLINE_INFILE ***************************/
- int do_stringline_infile(char *argv,int n)
- {
- int strspace, cccnt, ccnt = 0, lcnt = 0;
- int space_step = 200, nn;
- int old_stringstoresize;
- char *p, *zong;
- char temp2[200];
- int total_space = space_step;
- if((fp[0] = fopen(argv,"r"))==NULL) {
- fprintf(stdout,"ERROR: Cannot open infile %s\n",argv);
- fflush(stdout);
- exit(1);
- }
- if(stringstoresize == 0) {
- if((stringstore = (char *)exmalloc(total_space))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- }
- while(fgets(temp,200,fp[0])!=NULL) {
- p = temp;
- cccnt = 0;
- while(strgetstr(&p,temp2)) {
- strspace = strlen(temp2)+1;
- old_stringstoresize = stringstoresize;
- if((stringstoresize += strspace) >= total_space) {
- while(stringstoresize >= total_space)
- total_space += space_step;
- if((zong = (char *)malloc(total_space))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- memcpy(zong,stringstore,old_stringstoresize);
- free(stringstore);
- stringstore = zong;
- }
- strcpy(stringstore + stringstart,temp2);
- stringstart += strspace;
- stringscnt++;
- cccnt++;
- }
- if(lcnt == 0) {
- ccnt = cccnt;
- lcnt++;
- } else if(ccnt != cccnt) {
- if(cccnt != 0) {
- fprintf(stdout,"ERROR: File %s is not a true table file (line %d has %d cols instead of %d).\n",
- argv,lcnt+1,cccnt,ccnt);
- fflush(stdout);
- exit(1);
- } else {
- continue;
- }
- } else {
- lcnt++;
- }
- }
- if(stringscnt <= n) {
- fprintf(stdout,"ERROR: Invalid or missing data.\n");
- fflush(stdout);
- exit(1);
- }
- if(strings == 0) {
- if((strings = (char **)malloc(stringscnt * sizeof(char *)))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- } else {
- if((strings = (char **)realloc((char *)strings,stringscnt * sizeof(char *)))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- }
- p = stringstore;
- nn = 0;
- while(nn < stringscnt) {
- strings[nn] = p;
- while(*p != ENDOFSTR)
- p++;
- p++;
- nn++;
- }
- fclose(fp[0]);
- return ccnt;
- }
- /************************* DO_OTHER_STRINGLINE_INFILE ***************************/
- void do_other_stringline_infiles(char *argv[],char c)
- {
- int n;
- int sum, thiscolcnt, last_stringscnt, this_stringscnt, rowcnt=0, thisrowcnt;
- if((cntr = (int *)malloc(infilecnt*sizeof(int)))==NULL) {
- fprintf(stdout,"ERROR: Out of memory.\n");
- fflush(stdout);
- exit(1);
- }
- cntr[0] = stringscnt;
- sum = cntr[0];
- if(c == 'J') {
- if((rowcnt = stringscnt/colcnt) * colcnt != stringscnt) {
- fprintf(stdout,
- "ERROR: Incomplete table 1 : all rows must have same number of columns for this option.\n");
- fflush(stdout);
- exit(1);
- }
- }
- for(n=1;n<infilecnt;n++) {
- last_stringscnt = stringscnt;
- thiscolcnt = do_stringline_infile(argv[n+1],stringscnt);
- switch(c) {
- case('j'):
- if(thiscolcnt != colcnt) {
- fprintf(stdout,"ERROR: Count of columns incompatible in the input files.\n");
- fflush(stdout);
- exit(1);
- }
- break;
- case('W'):
- if(thiscolcnt != colcnt) {
- fprintf(stdout,"ERROR: Count of columns incompatible in the input files.\n");
- fflush(stdout);
- exit(1);
- }
- break;
- case('J'):
- this_stringscnt = stringscnt - last_stringscnt;
- if((thisrowcnt = this_stringscnt/thiscolcnt) * thiscolcnt != this_stringscnt) {
- fprintf(stdout,
- "ERROR: Table %d incomplete: all rows must have same number of columns for this option.\n",n+1);
- fflush(stdout);
- exit(1);
- }
- if(thisrowcnt != rowcnt) {
- fprintf(stdout,"ERROR: File %d does not have same number of rows as 1st file.\n",n+1);
- fflush(stdout);
- exit(1);
- }
- break;
- }
- cntr[n] = stringscnt - sum;
- sum += cntr[n];
- }
- if(c == 'J')
- colcnt = rowcnt; /* held temporarily in global */
- }
- /************************* DO_STRING_INFILE ***************************/
- void do_string_infile(char *argv)
- {
- int strspace;
- int space_step = 200, startstringscnt = stringscnt, n;
- int old_stringstoresize;
- char *p;
- char temp2[200];
- int total_space = space_step;
- if((fp[0] = fopen(argv,"r"))==NULL) {
- sprintf(errstr,"Cannot open infile %s\n",argv);
- do_error();
- }
- if(stringstoresize == 0) {
- if((stringstore = (char *)malloc(total_space))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- }
- while(fgets(temp,200,fp[0])!=NULL) {
- p = temp;
- while(strgetstr(&p,temp2)) {
- strspace = strlen(temp2)+1;
- old_stringstoresize = stringstoresize;
- if((stringstoresize += strspace) >= total_space) {
- while(stringstoresize >= total_space)
- total_space += space_step;
- if((stringstore = (char *)realloc((char *)stringstore,total_space))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- }
- strcpy(stringstore + stringstart,temp2);
- stringstart += strspace;
- stringscnt++;
- }
- }
- if(stringscnt <=0) {
- sprintf(errstr,"Invalid or missing data.\n");
- do_error();
- }
- if(strings == 0) {
- if((strings = (char **)malloc(stringscnt * sizeof(char *)))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- } else {
- if((strings = (char **)realloc((char *)strings,stringscnt * sizeof(char *)))==NULL) {
- sprintf(errstr,"Out of Memory\n");
- do_error();
- }
- }
- p = stringstore;
- n = 0;
- while(n < startstringscnt) {
- while(*p != ENDOFSTR)
- p++;
- p++;
- n++;
- }
- while(n < stringscnt) {
- strings[n] = p;
- while(*p != ENDOFSTR)
- p++;
- p++;
- n++;
- }
- fclose(fp[0]);
- }
- /************************* TEST_WARP_DATA ***************************/
- void test_warp_data(void)
- {
- int n = 0;
- if(number[n] < 0) {
- sprintf(errstr,"Negative time in breakpoint file: Cannot proceed.\n");
- do_error();
- exit(1);
- }
- if(number[1] < 1.0/1024.0 || number[1] > 1024.0) {
- sprintf(errstr,"Dubious Timestretch value (%lf) in brkpnt file.\n",number[1]);
- do_error();
- exit(1);
- }
- for(n = 2; n <firstcnt; n+=2) {
- if(number[n] <= number[n-2]) {
- sprintf(errstr,"Times (%lf & %lf) not in increasing order in brkpnt file.\n",number[n-2],number[n]);
- do_error();
- exit(1);
- }
- if(number[n+1] < 1.0/1024.0 || number[n+1] > 1024.0) {
- sprintf(errstr,"Dubious Timestretch value (%lf) in brkpnt file.\n",number[n+1]);
- do_error();
- exit(1);
- }
- }
- for(n = firstcnt; n <cnt; n++) {
- if(number[n] < 0.0) {
- sprintf(errstr,"Negative time (%lf) given in 2nd file: Cannot proceed.\n",number[n]);
- do_error();
- exit(1);
- }
- }
- }
|