| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274 |
- /*
- * 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>
- //#ifdef unix
- #define round(x) lround((x))
- //#endif
- #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 inumber;
- 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(inumber = samesize(intime0,intime1,insize0,insize1,duration));
- fnum = cntevents(duration,insize0,insize1); /* 2 */
- inumber = round(fnum);
- if(inumber<=1) /* 3 */
- return(1);
- pos = (double *)exmalloc((inumber+1) * sizeof(double));
- fnumber = (double)(inumber); /* 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,inumber);
- pos[inumber] = intime1;
- return(inumber+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 inumber;
- double fnum, size; /* 1 */
- size = (insize0+insize1)/2;
- fnum = duration/size;
- inumber = round(fnum);
- size = duration/(double)inumber;
- pos = (double *)exmalloc((inumber+1) * sizeof(double));
- approxtimes(intime0,size,inumber);
- pos[inumber] = intime1;
- return(inumber+1);
- }
- /************************ APPROXTIME ***************************
- *
- * Calculate time-positions of equally spaced events.
- */
- void approxtimes(double intime0,double size,int inumber)
- { int k;
- double *q = pos;
- *q++ = intime0;
- for(k=1;k<inumber;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 inumber)
- { int n;
- double sdiff = s1-s0, tdiff = t1-t0, d1, d2, d3, *q = pos;
- *q++ = t0;
- for(n=1;n<inumber;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 dtemp = *d0;
- *d0 = *d1;
- *d1 = dtemp;
- }
- /**************************** 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;
- }
- }
- //RWD Nov 2025 nb this func uses global var 'number' (columns.h), TODO: make local, somehow!
- void bublsort(void) {
- int n, m;
- double dtemp;
- for(n=0;n<cnt-1;n++) {
- for(m = n; m<cnt; m++) {
- if(number[m] < number[n]) {
- dtemp = number[n];
- number[n] = number[m];
- number[m] = dtemp;
- }
- }
- }
- }
- /************************* 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);
- }
- }
- }
|