columns1.c 38 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274
  1. /*
  2. * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. /* columns */
  22. #include <columns.h>
  23. //#ifdef unix
  24. #define round(x) lround((x))
  25. //#endif
  26. #define CALCLIM 0.001
  27. #define M 7
  28. #define NSTACK 50
  29. #define MIDDLE_C_MIDI_OCTAVE 5
  30. #define CONVERT_LOG10_TO_LOG2 (double)3.321928
  31. #define LOW_A 6.875 /* Frequency of A below MIDI 0 */
  32. double cntevents(double,double,double);
  33. int samesize(double,double,double,double,double);
  34. void approxtimes(double,double,int);
  35. void getetime(double,double,double,double,int);
  36. double gethibnd(double,double,double,double,double);
  37. double getlobnd(double,double,double,double,double);
  38. double refinesize(double,double,double,double,double,double);
  39. void prnt_pitchclass(int,int);
  40. int strgetfloat_db(char **,double *);
  41. static void bublsort(void);
  42. static void test_warp_data(void);
  43. int *cntr;
  44. char **strings = 0;
  45. char *stringstore;
  46. int stringscnt = 0;
  47. int stringstoresize = 0, stringstart = 0;
  48. /************************ TIMEVENTS ******************************
  49. *
  50. * Generates event positions from startsize and end size
  51. *
  52. * Let start-time be T0 and end time be T1
  53. * Let start size be S0 and end S1
  54. *
  55. * number of event is given by :-
  56. *
  57. * N = (T1-T0) log S1
  58. * ------- e__
  59. * (S1-S0) S0
  60. *
  61. * In general this will be non-integral, and we should
  62. * round N to an integer, and recalculate S1 by successive
  63. * approximation.
  64. *
  65. * Then positions of events are given by
  66. *
  67. * for X = 0 to N (S1-S0)
  68. * ----- X
  69. * T = (S1T0 - S0T1) S0(T1 - T0) (T1-T0)
  70. * s ----------- + ---------- e
  71. * (S1 - S0) (S1 - S0)
  72. *
  73. * If difference in eventsizes input to the main program is very small
  74. * then infinite values result. To avoid this we divert the calculation
  75. * to another routine (which assumes the input values are equal.
  76. * The value of CALCLIM = 0.001. (LArger than usual i.e. 0.05)
  77. *
  78. * If size values are so BIG that they exceed segment duration,
  79. * eventsize becomes segment duration and a Warning is printed.
  80. *(1) events approx same size.
  81. *(2) events of different sizes, find the number of events which approx
  82. * fit in the duration.
  83. *(3) If there's only one event .. that's it.
  84. *(4) Note the error (difference between approximated whole number of events
  85. * and the actual,non-integer, number of events).
  86. *(5) Calculate acceptable bounds on a new endeventsize, which will give
  87. * a better fit of the integer number of events within the given duration.
  88. *(6) Find an acceptable final value for endeventsize by successive approx
  89. * NB we don't know whether the function increases as d increases
  90. * so lobound may be > hibound. However, the maths of the method will
  91. * still work, just inverting the sense of the search!!
  92. *(7) Calculate the inital times of the events.
  93. *
  94. * This function returns the number of events within the time-interval,
  95. * and returns the times of these events in the array-of-doubles pos.
  96. */
  97. int timevents(double intime0,double intime1,double insize0,double insize1)
  98. {
  99. int inumber;
  100. double fnum, fnumber, error;
  101. double lobound, hibound, duration;
  102. if(flteq(insize0,0.0) || flteq(insize1,0.0)) {
  103. sprintf(errstr,"Event size of zero encountered.\n");
  104. do_error();
  105. }
  106. duration = (intime1-intime0);
  107. if(duration<=0.0) {
  108. sprintf(errstr,"Inconsistent input times (2nd before 1st).\n");
  109. do_error();
  110. }
  111. if(fabs(insize1-insize0)<CALCLIM) /* 1 */
  112. return(inumber = samesize(intime0,intime1,insize0,insize1,duration));
  113. fnum = cntevents(duration,insize0,insize1); /* 2 */
  114. inumber = round(fnum);
  115. if(inumber<=1) /* 3 */
  116. return(1);
  117. pos = (double *)exmalloc((inumber+1) * sizeof(double));
  118. fnumber = (double)(inumber); /* 4 */
  119. error = fabs(fnum - fnumber);
  120. lobound = insize1; /* 5 */
  121. hibound = insize1;
  122. if(fnum<fnumber)
  123. hibound = gethibnd(fnum,fnumber,insize1,insize0,duration);
  124. if(fnum>fnumber)
  125. lobound = getlobnd(fnum,fnumber,insize1,insize0,duration);
  126. if(error > FLTERR) { /* 6 */
  127. if(lobound < hibound) /* LOBOUND is a HIGH SIZE for a LOW COUNT!! */
  128. swap(&hibound,&lobound);
  129. insize1 = refinesize(hibound,lobound,fnumber,error,duration,insize0);
  130. } else {
  131. insize1 = (hibound+lobound)/2;
  132. } /* 7 */
  133. getetime(intime0,intime1,insize0,insize1,inumber);
  134. pos[inumber] = intime1;
  135. return(inumber+1);
  136. }
  137. /*************************** CNTEVENTS *****************************/
  138. double cntevents(double dur,double s0,double s1)
  139. { double f1,f2;
  140. f1 = dur;
  141. f2 = s1-s0;
  142. f1 /= f2;
  143. f2 = s1/s0;
  144. f2 = log(f2);
  145. f1 *= f2;
  146. return(fabs(f1));
  147. }
  148. /******************************* SAMESIZE *******************************
  149. *
  150. * get event positions, if eventsize approx same throughout segment.
  151. *
  152. *(1) Get average size, find number of events and round to nearest int.
  153. *(3) Recalculate size, and thence event times.
  154. */
  155. int samesize
  156. (double intime0,double intime1,double insize0,double insize1,double duration)
  157. {
  158. int inumber;
  159. double fnum, size; /* 1 */
  160. size = (insize0+insize1)/2;
  161. fnum = duration/size;
  162. inumber = round(fnum);
  163. size = duration/(double)inumber;
  164. pos = (double *)exmalloc((inumber+1) * sizeof(double));
  165. approxtimes(intime0,size,inumber);
  166. pos[inumber] = intime1;
  167. return(inumber+1);
  168. }
  169. /************************ APPROXTIME ***************************
  170. *
  171. * Calculate time-positions of equally spaced events.
  172. */
  173. void approxtimes(double intime0,double size,int inumber)
  174. { int k;
  175. double *q = pos;
  176. *q++ = intime0;
  177. for(k=1;k<inumber;k++) {
  178. *q = *(q-1) + size;
  179. q++;
  180. }
  181. }
  182. /******************************* GETETIME ********************************
  183. *
  184. * Calculate time-positions of events that vary in size between s0 and s1.
  185. */
  186. void getetime(double t0,double t1,double s0,double s1,int inumber)
  187. { int n;
  188. double sdiff = s1-s0, tdiff = t1-t0, d1, d2, d3, *q = pos;
  189. *q++ = t0;
  190. for(n=1;n<inumber;n++) {
  191. d1 = sdiff/tdiff;
  192. d1 *= (double)n;
  193. d1 = exp(d1);
  194. d2 = s0*tdiff;
  195. d2 /= sdiff;
  196. d1 *= d2;
  197. d2 = s1*t0;
  198. d3 = s0*t1;
  199. d2 -= d3;
  200. d2 /= sdiff;
  201. d1 += d2;
  202. *q++ = d1;
  203. }
  204. }
  205. /****************************** GETHIBND *****************************
  206. *
  207. * Find SMALLER VALUE of SIZE, to GIVE a LARGER VALUE of NO-OF-SEGS
  208. * which will act as an UPPER BOUND to be used for searching
  209. * for an endsize that will give the integer number of events in the duration,
  210. *
  211. * (0) Start by REDUCING size, to give BIGGER fnum.
  212. *(1) If we're going downwards, (try -ve) and we go below zero,restore value
  213. * and subtract less.
  214. *(2) If the fnums are moving in the opposite direction to what we expect,
  215. * restore values and increment in the opposite direction,but only half
  216. * as much!
  217. */
  218. double gethibnd(double fnum,double fnumber,double insize1,
  219. double insize0,double duration)
  220. { double lastfnum, try = -1.0; /* 0 */
  221. double bound = insize1;
  222. while(fnum<fnumber) {
  223. lastfnum = fnum;
  224. bound += try;
  225. while(bound<=0) { /* 1 */
  226. bound -= try;
  227. try /= 2.0;
  228. bound += try;
  229. }
  230. fnum = cntevents(duration,insize0,bound);
  231. if(fnum<lastfnum) { /* 2 */
  232. fnum=lastfnum;
  233. bound -= try;
  234. try = -(try/2.0);
  235. }
  236. }
  237. return(bound);
  238. }
  239. /****************************** GETLOBND *****************************
  240. *
  241. *
  242. * Find LARGER VALUE of SIZE, to GIVE a SMALLER VALUE of NO-OF-SEGS
  243. * which will act as a LOWER BOUND to be used for searching
  244. * for an endsize that will give the integer number of events in the duration,
  245. *
  246. * LOBOUND is a LARGER value of SIZE to give SMALLER value of NUM-OF-SEGS.
  247. *
  248. * (0) Start by INCREASING size, to give SMALLER fnum.
  249. * (1) If we're going downwards, (try -ve) and we go below zero, restore
  250. * propr value of bound, value and subtract less.
  251. * (2) If the fnums are moving in the opposite direction to what we expect,
  252. * (fnum > lastfnum, while we're trying to DECREASE fnum)
  253. * restore values and increment in the opposite direction,but only half
  254. * as much!
  255. */
  256. double getlobnd(double fnum,double fnumber,double insize1,
  257. double insize0,double duration)
  258. { double try = 1.0;
  259. double lastfnum;
  260. double bound = insize1;
  261. while(fnum>fnumber) {
  262. lastfnum = fnum;
  263. bound += try;
  264. while(bound<=0) {
  265. bound -= try;
  266. try /= 2;
  267. bound += try;
  268. }
  269. fnum = cntevents(duration,insize0,bound);
  270. if(fnum>lastfnum) {
  271. fnum =lastfnum;
  272. bound -= try;
  273. try = -(try/2);
  274. }
  275. }
  276. return(bound);
  277. }
  278. /***************************** REFINESIZE ******************************
  279. *
  280. * refine size of final event to reduce error within bounds.
  281. */
  282. double refinesize(double hibound,double lobound,double fnumber,
  283. double error,double duration,double insize0)
  284. { double size = (hibound+lobound)/2, fnum;
  285. while(error>(FLTERR)) {
  286. size = (hibound+lobound)/2;
  287. fnum = cntevents(duration,insize0,size);
  288. error = fabs(fnumber-fnum);
  289. if(error>FLTERR) {
  290. if(fnum<fnumber)
  291. lobound = size;
  292. else
  293. hibound = size;
  294. }
  295. }
  296. return(size);
  297. }
  298. /**************************STRGETFLOAT **************************
  299. * takes a pointer TO A POINTER to a string. If it succeeds in finding
  300. * a float it returns the float value (*val), and it's new position in the
  301. * string (*str).
  302. */
  303. int strgetfloat(char **str,double *val)
  304. { char *p, *q, *end;
  305. double numero;
  306. int point, valid;
  307. for(;;) {
  308. point = 0;
  309. p = *str;
  310. while(isspace(*p))
  311. p++;
  312. q = p;
  313. if(!isdigit(*p) && *p != '.' && *p!='-')
  314. return(0);
  315. if(*p == '.'|| *p == '-') {
  316. if(*p == '-') {
  317. p++;
  318. } else {
  319. point++;
  320. p++;
  321. }
  322. }
  323. for(;;) {
  324. if(*p == '.') {
  325. if(point)
  326. return(0);
  327. else {
  328. point++;
  329. p++;
  330. continue;
  331. }
  332. }
  333. if(isdigit(*p)) {
  334. p++;
  335. continue;
  336. } else {
  337. if(!isspace(*p) && *p!=ENDOFSTR)
  338. return(0);
  339. else {
  340. end = p;
  341. p = q;
  342. valid = 0;
  343. while(p!=end) {
  344. if(isdigit(*p))
  345. valid++;
  346. p++;
  347. }
  348. if(valid) {
  349. if(sscanf(q,"%lf",&numero)!=1)
  350. return(0);
  351. *val = numero;
  352. *str = end;
  353. return(1);
  354. }
  355. return(0);
  356. }
  357. }
  358. }
  359. }
  360. return(0); /* NOTREACHED */
  361. }
  362. /**************************STRGETFLOAT_DB **************************
  363. * takes a pointer TO A POINTER to a string. If it succeeds in finding
  364. * a float it returns the float value (*val), and it's new position in the
  365. * string (*str). IT JUMPS OVER 'db'
  366. */
  367. int strgetfloat_db(char **str,double *val)
  368. {
  369. char *p, *q, *end;
  370. double numero;
  371. int point, valid;
  372. for(;;) {
  373. point = 0;
  374. p = *str;
  375. while(isspace(*p))
  376. p++;
  377. q = p;
  378. if(!isdigit(*p) && *p != '.' && *p!='-')
  379. return(0);
  380. if(*p == '.'|| *p == '-') {
  381. if(*p == '-') {
  382. p++;
  383. } else {
  384. point++;
  385. p++;
  386. }
  387. }
  388. for(;;) {
  389. if(*p == '.') {
  390. if(point)
  391. return(0);
  392. else {
  393. point++;
  394. p++;
  395. continue;
  396. }
  397. }
  398. if(isdigit(*p)) {
  399. p++;
  400. continue;
  401. } else {
  402. if(!isspace(*p) && *p!=ENDOFSTR && !(*p=='d' || *p=='D') && !(*(p+1)!='b' || *(p+1)!='B'))
  403. return(0);
  404. else {
  405. end = p;
  406. p = q;
  407. valid = 0;
  408. while(p!=end) {
  409. if(isdigit(*p))
  410. valid++;
  411. p++;
  412. }
  413. if(*end=='d' || *end=='D')
  414. end += 2;
  415. if(valid) {
  416. if(sscanf(q,"%lf",&numero)!=1)
  417. return(0);
  418. *val = numero;
  419. *str = end;
  420. return(1);
  421. }
  422. return(0);
  423. }
  424. }
  425. }
  426. }
  427. return(0); /* NOTREACHED */
  428. }
  429. /**************************STRGETSTR ***************************/
  430. int strgetstr(char **str,char *str2)
  431. {
  432. char *p, *q, c;
  433. p = *str;
  434. while(isspace(*p))
  435. p++;
  436. if(*p == ENDOFSTR)
  437. return(0);
  438. q = p;
  439. while(!isspace(*p))
  440. p++;
  441. c = *p;
  442. *p = ENDOFSTR;
  443. strcpy(str2,q);
  444. *p = c;
  445. *str = p;
  446. return(1);
  447. }
  448. /************************** HZTOMIDI ************************/
  449. double miditohz(double midi)
  450. { double frq;
  451. frq = midi;
  452. frq += 3.0;
  453. frq /= 12.0;
  454. frq = pow((double)2,frq);
  455. frq *= LOW_A;
  456. return(frq);
  457. }
  458. /****************************** MIDITOHZ *************************/
  459. double hztomidi(double hz)
  460. { double midi;
  461. midi = hz;
  462. midi /= LOW_A;
  463. midi = log10(midi) * CONVERT_LOG10_TO_LOG2;
  464. midi *= 12.0;
  465. midi -= 3.0;
  466. return(midi);
  467. }
  468. /*********************** RNDPERM ************************/
  469. void rndperm(double *z)
  470. {
  471. int n,t;
  472. int k = cnt * sizeof(double);
  473. permm = (double *)exmalloc(k*2);
  474. memset((char *)permm,0,k*2);
  475. permmm = permm + cnt;
  476. for(n=0;n<cnt;n++) {
  477. t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
  478. if(t==n)
  479. prefix(z,n);
  480. else
  481. insert(z,n,t);
  482. }
  483. memcpy((char *)z,(char *)permmm,k);
  484. free(permm);
  485. }
  486. /*********************** RNDPERM2 ************************
  487. *
  488. * Does not malloc and free perm internally.
  489. */
  490. void rndperm2(double *z)
  491. { int n,t;
  492. int k = cnt * sizeof(double);
  493. memset((char *)permm,0,k*2);
  494. permmm = permm + cnt;
  495. for(n=0;n<cnt;n++) {
  496. t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
  497. if(t==n)
  498. prefix(z,n);
  499. else
  500. insert(z,n,t);
  501. }
  502. memcpy((char *)z,(char *)permmm,k);
  503. }
  504. /*********************** MULTRNDPERM ************************
  505. * START
  506. * orig orig orig
  507. * |--------|--------|--------|
  508. * 1ST PERM
  509. * perm1 orig orig
  510. * |--------|--------|--------|
  511. * NEXT PERM
  512. * perm1 perm2 orig
  513. * |--------|--------|--------|
  514. * MEMCPY
  515. * perm1=perm2 orig orig
  516. * |--------|--------|--------|
  517. * go to NEXT PERM
  518. */
  519. void multrndperm(double *blok1)
  520. { int n, m;
  521. double lastenditem, *blok2, *blok3;
  522. int oneblok = cnt * sizeof(double);
  523. int twobloks = oneblok*2;
  524. int threebloks = oneblok*3;
  525. blok1 = (double *)exrealloc((char *)blok1,threebloks);
  526. blok2 = blok1 + cnt;
  527. blok3 = blok2 + cnt;
  528. memcpy((char *)blok2,(char *)blok1,oneblok);
  529. memcpy((char *)blok3,(char *)blok1,oneblok);
  530. permm = (double *)exmalloc(cnt * 2 * sizeof(double));
  531. rndperm2(blok1); /* perm 1st copy */
  532. for(n=0;n<cnt;n++)
  533. do_valout(blok1[n]);
  534. for(m=1;m<ifactor;m++) { /* now do perms on 2nd copy */
  535. lastenditem = *(blok2-1);
  536. do {
  537. rndperm2(blok2);
  538. } while(blok2[0]==lastenditem);
  539. /* Avoid element repeat at block boundaries */
  540. for(n=0;n<cnt;n++)
  541. do_valout(blok2[n]);
  542. memcpy((char *)blok1,(char *)blok2,twobloks);
  543. /* Move perm along & restore orig set */
  544. }
  545. fflush(stdout);
  546. free(permm);
  547. }
  548. /************************** INSERT *************************/
  549. void insert(double *z,int m,int t)
  550. {
  551. shuffle(t+1,m);
  552. permmm[t+1] = z[m];
  553. }
  554. /************************** PREFIX ***************************/
  555. void prefix(double *z,int m)
  556. { permmm--;
  557. permmm[0] = z[m];
  558. }
  559. /*************************** SHUFFLE ***********************/
  560. void shuffle(int k,int m)
  561. {
  562. int n;
  563. double *i;
  564. if(k/2 > m) { /* shuffle up */
  565. i = &permmm[m];
  566. for(n=m;n>k;n--) {
  567. *i = *(i-1);
  568. i--;
  569. }
  570. } else { /* shuffle down */
  571. i = &permmm[0];
  572. for(n=0;n<k;n++) {
  573. *(i-1) = *i;
  574. i++;
  575. }
  576. permmm--; /* Move base of perm down by 1 */
  577. }
  578. }
  579. /******************************** EXMALLOC ****************************/
  580. char *exmalloc(int n)
  581. {
  582. char *p;
  583. if((p = (char *)malloc(n))==NULL) {
  584. sprintf(errstr,"ERROR: Memory allocation failed\n");
  585. do_error();
  586. }
  587. return(p);
  588. }
  589. /************************ READ_INPUT_FILE ****************************/
  590. void read_input_file(FILE *fpp)
  591. { char *p;
  592. double *number2;
  593. while(fgets(temp,20000,fpp)!=NULL) {
  594. p = temp;
  595. while(strgetfloat(&p,&number[cnt])) {
  596. if(++cnt >= arraysize) {
  597. arraysize += BIGARRAY;
  598. /* NOVEMBER 2001 NEW */
  599. number2 = (double *)malloc(arraysize*sizeof(double));
  600. memcpy((void *)number2,(void *)number,cnt * sizeof(double));
  601. number = number2;
  602. /* NOVEMBER 2001 OLD
  603. number = (double *)exrealloc((char *)number,arraysize*sizeof(double));
  604. */
  605. }
  606. }
  607. }
  608. }
  609. /************************* DO_INFILE ***************************/
  610. void do_infile(char *argv)
  611. {
  612. char *p;
  613. double *number2;
  614. if((fp[0] = fopen(argv,"r"))==NULL) {
  615. sprintf(errstr,"Cannot open infile %s\n",argv);
  616. do_error();
  617. }
  618. while(fgets(temp,20000,fp[0])!=NULL) {
  619. p = temp;
  620. while(strgetfloat(&p,&number[cnt])) {
  621. if(++cnt >= arraysize) {
  622. arraysize += BIGARRAY;
  623. /* NOVEMBER 2001 NEW */
  624. if((number2=(double *)malloc(arraysize*sizeof(double)))==NULL) {
  625. sprintf(errstr,"Out of memory for more numbers at %d numbers\n",cnt);
  626. do_error();
  627. }
  628. memcpy((void *)number2,(void *)number,cnt * sizeof(double));
  629. number = number2;
  630. /* NOVEMBER 2001 OLD
  631. if((number=(double *)exrealloc((char *)number,arraysize*sizeof(double)))==NULL) {
  632. sprintf(errstr,"Out of memory for more numbers at %d numbers\n",cnt);
  633. do_error();
  634. }
  635. */
  636. }
  637. }
  638. }
  639. if(cnt <=0) {
  640. sprintf(errstr,"Invalid or missing data.\n");
  641. do_error();
  642. }
  643. fclose(fp[0]);
  644. }
  645. /************************* DO_DB_INFILE ***************************/
  646. void do_DB_infile(char *argv)
  647. {
  648. char *p;
  649. if((fp[0] = fopen(argv,"r"))==NULL) {
  650. sprintf(errstr,"Cannot open infile %s\n",argv);
  651. do_error();
  652. }
  653. while(fgets(temp,20000,fp[0])!=NULL) {
  654. p = temp;
  655. while(strgetfloat_db(&p,&number[cnt])) {
  656. if(++cnt >= arraysize) {
  657. arraysize += BIGARRAY;
  658. number=(double *)exrealloc((char *)number,arraysize*sizeof(double));
  659. }
  660. }
  661. }
  662. if(cnt <=0) {
  663. sprintf(errstr,"Invalid or missing data.\n");
  664. do_error();
  665. }
  666. fclose(fp[0]);
  667. }
  668. /************************* DO_PITCHTEXT_INFILE ***************************/
  669. void do_pitchtext_infile(char *argv)
  670. {
  671. char *p;
  672. char temp2[200];
  673. if((fp[0] = fopen(argv,"r"))==NULL) {
  674. sprintf(errstr,"Cannot open infile %s\n",argv);
  675. do_error();
  676. }
  677. while(fgets(temp,200,fp[0])!=NULL) {
  678. p = temp;
  679. while(strgetstr(&p,temp2)) {
  680. number[cnt] = texttomidi(temp2);
  681. if(++cnt >= arraysize) {
  682. arraysize += BIGARRAY;
  683. number=(double *)exrealloc((char *)number,arraysize*sizeof(double));
  684. }
  685. }
  686. }
  687. if(cnt <=0) {
  688. sprintf(errstr,"ERROR: Invalid or missing data.\n");
  689. do_error();
  690. }
  691. fclose(fp[0]);
  692. }
  693. /************************* DO_OTHER_INFILE **********************/
  694. void do_other_infiles(char *argv[])
  695. {
  696. int n;
  697. if(infilecnt>2)
  698. fp = (FILE **)exrealloc((char *)fp,infilecnt*sizeof(FILE *));
  699. firstcnt = cnt;
  700. for(n=1;n<infilecnt;n++) {
  701. if((fp[n] = fopen(argv[n+1],"r"))==NULL) {
  702. sprintf(errstr,"\nCannot open file %s to read.\n",argv[n+1]);
  703. do_error();
  704. }
  705. read_input_file(fp[n]);
  706. if (flag == 'A' && ro =='e') {
  707. file_cnt[n] = cnt - firstcnt;
  708. firstcnt = cnt;
  709. } else if((flag=='J' || (flag=='C' && ro == 'c')) && cnt != firstcnt * (n+1)) {
  710. sprintf(errstr,"Input file %d has wrong number of values to match previous column lengths.\n",n+1);
  711. do_error();
  712. }
  713. }
  714. if (flag == 'w' && (ro == 't' || ro == 'o')) {
  715. test_warp_data();
  716. }
  717. }
  718. /********************** DO_OUTFILE *****************************/
  719. void do_outfile(char *argv) {
  720. if((fp[1] = fopen(argv,"w"))==NULL) {
  721. sprintf(errstr,"Cannot open file %s to write.\n",argv);
  722. do_error();
  723. exit(1);
  724. }
  725. }
  726. /**************************** QIKSORT ******************************/
  727. void qiksort(void) {
  728. bublsort();
  729. }
  730. /************************ BELLPERM1 ***************************/
  731. void bellperm1(void)
  732. { int n;
  733. for(n=0;n<cnt;n+=2)
  734. swap(&number[n], &number[n+1]);
  735. }
  736. /************************** BELLPERM2 ******************************/
  737. void bellperm2(void)
  738. { int n;
  739. for(n=2;n<cnt;n+=2)
  740. swap(&number[n], &number[n-1]);
  741. }
  742. /************************* BELLPERM3 ******************************/
  743. void bellperm3(void)
  744. { int n;
  745. for(n=2;n<cnt;n+=2)
  746. swap(&number[n], &number[n+1]);
  747. }
  748. /***************************** SWAP *******************************/
  749. void swap(double *d0,double *d1)
  750. {
  751. double dtemp = *d0;
  752. *d0 = *d1;
  753. *d1 = dtemp;
  754. }
  755. /**************************** FLTEQ *******************************/
  756. int flteq(double f1,double f2)
  757. {
  758. double upperbnd, lowerbnd;
  759. upperbnd = f2 + FLTERR;
  760. lowerbnd = f2 - FLTERR;
  761. if((f1>upperbnd) || (f1<lowerbnd))
  762. return(0);
  763. return(1);
  764. }
  765. /***************************** ELIMINATE ********************************/
  766. void eliminate(int m)
  767. {
  768. int n;
  769. for(n=m+1;n<cnt;n++)
  770. number[n-1] = number[n];
  771. cnt--;
  772. }
  773. /***************************** EXREALLOC *****************************/
  774. char *exrealloc(char *p,int k)
  775. {
  776. char *q;
  777. q = exmalloc(k);
  778. memcpy(q,p,k);
  779. free(p);
  780. return(q);
  781. }
  782. /****************************** TEXTTOMIDI ******************************/
  783. double texttomidi(char *str)
  784. {
  785. int pitch, octave, octshift = 0;
  786. char *p = str;
  787. if(!strncmp(str,"B#",2) || !strncmp(str,"b#",2))
  788. octshift--;
  789. if((str = get_pitchclass(str,&pitch,1))==(char *)0) {
  790. sprintf(errstr,"Unknown pitch %s\n",p);
  791. do_error();
  792. }
  793. if(sscanf(str,"%d",&octave)!=1) {
  794. sprintf(errstr,"unknown pitch-string %s or no octave value\n",p);
  795. do_error();
  796. }
  797. octave += (MIDDLE_C_MIDI_OCTAVE + octshift);
  798. pitch += (octave * 12);
  799. return((double)pitch);
  800. }
  801. /****************************** GET_PITCHCLASS ******************************/
  802. char *get_pitchclass(char *str,int *pitch,int with_octave)
  803. {
  804. switch(*str++) {
  805. case('c'): case('C'): *pitch = 0; break;
  806. case('d'): case('D'): *pitch = 2; break;
  807. case('e'): case('E'): *pitch = 4; break;
  808. case('f'): case('F'): *pitch = 5; break;
  809. case('g'): case('G'): *pitch = 7; break;
  810. case('a'): case('A'): *pitch = 9; break;
  811. case('b'): case('B'): *pitch = 11; break;
  812. default: return((char *)0);
  813. }
  814. switch(*str++) {
  815. case('#'): (*pitch)++; break;
  816. case('b'): (*pitch)--; break;
  817. default: str--; break;
  818. }
  819. if(with_octave) {
  820. if(*str==ENDOFSTR)
  821. return((char *)0);
  822. }
  823. return(str);
  824. }
  825. /******************************** LOGO() **********************************/
  826. void logo(void)
  827. { printf("\t ***************************************************\n");
  828. printf("\t * COMPOSERS DESKTOP PROJECT *\n");
  829. printf("\t %s $Revision: 1.8 $\n",PROG);
  830. printf("\t * Manipulate or Generate columns of numbers *\n");
  831. printf("\t * by TREVOR WISHART *\n");
  832. printf("\t ***************************************************\n\n");
  833. }
  834. /****************************** PITCHTOTEXT ******************************/
  835. void pitchtotext(int midi)
  836. { int oct, n;
  837. int basetone;
  838. double diff;
  839. for(n=0;n<cnt;n++) {
  840. if(midi) {
  841. if(number[n] < MIDIMIN || number[n] > MIDIMAX) {
  842. fprintf(stdout,"ERROR: MIDI value %d (%lf) is out of range for conversion to pitch.\n", n+1,number[n]);
  843. fflush(stdout);
  844. exit(1);
  845. }
  846. } else {
  847. if(number[n] < MIDIMINFRQ || number[n] > MIDIMAXFRQ) {
  848. fprintf(stdout,"ERROR: frq value %d (%lf) is out of range for conversion to pitch.\n", n+1,number[n]);
  849. fflush(stdout);
  850. exit(1);
  851. }
  852. }
  853. }
  854. for(n=0;n<cnt;n++) {
  855. if(!midi)
  856. number[n] = hztomidi(number[n]);
  857. oct = (int)(number[n]/12.0); /* TRUNCATE */
  858. oct -= 5;
  859. basetone = (int)floor(number[n]);
  860. diff = number[n] - (double)basetone;
  861. if(diff > .5)
  862. basetone++;
  863. prnt_pitchclass(basetone%12,oct);
  864. if(flteq(diff,0.0))
  865. strcat(errstr,"\n");
  866. else if(flteq(diff,0.5)) /* handle quarter tones */
  867. strcat(errstr,"+\n");
  868. else if(diff > .5)
  869. strcat(errstr,"(--)\n");
  870. else
  871. strcat(errstr,"(++)\n");
  872. fprintf(stdout,"INFO: %s",errstr);
  873. }
  874. fflush(stdout);
  875. }
  876. /****************************** PRNT_PITCHCLASS ******************************/
  877. void prnt_pitchclass(int z,int oct)
  878. {
  879. switch(z) {
  880. case(0): sprintf(errstr,"C%d",oct); break;
  881. case(1): sprintf(errstr,"C#%d",oct); break;
  882. case(2): sprintf(errstr,"D%d",oct); break;
  883. case(3): sprintf(errstr,"Eb%d",oct); break;
  884. case(4): sprintf(errstr,"E%d",oct); break;
  885. case(5): sprintf(errstr,"F%d",oct); break;
  886. case(6): sprintf(errstr,"F#%d",oct); break;
  887. case(7): sprintf(errstr,"G%d",oct); break;
  888. case(8): sprintf(errstr,"Ab%d",oct); break;
  889. case(9): sprintf(errstr,"A%d",oct); break;
  890. case(10): sprintf(errstr,"Bb%d",oct); break;
  891. case(11): sprintf(errstr,"B%d",oct); break;
  892. }
  893. }
  894. //RWD Nov 2025 nb this func uses global var 'number' (columns.h), TODO: make local, somehow!
  895. void bublsort(void) {
  896. int n, m;
  897. double dtemp;
  898. for(n=0;n<cnt-1;n++) {
  899. for(m = n; m<cnt; m++) {
  900. if(number[m] < number[n]) {
  901. dtemp = number[n];
  902. number[n] = number[m];
  903. number[m] = dtemp;
  904. }
  905. }
  906. }
  907. }
  908. /************************* DO_OTHER_STRINGLINE_INFILE ***************************/
  909. int do_other_stringline_infile(char *argv)
  910. {
  911. int cols;
  912. /*
  913. cnt = stringscnt; DONE PREVIOUSLY
  914. */
  915. cols = do_stringline_infile(argv,cnt);
  916. stringscnt -= cnt;
  917. return cols;
  918. }
  919. /************************* DO_STRINGLINE_INFILE ***************************/
  920. int do_stringline_infile(char *argv,int n)
  921. {
  922. int strspace, cccnt, ccnt = 0, lcnt = 0;
  923. int space_step = 200, nn;
  924. int old_stringstoresize;
  925. char *p, *zong;
  926. char temp2[200];
  927. int total_space = space_step;
  928. if((fp[0] = fopen(argv,"r"))==NULL) {
  929. fprintf(stdout,"ERROR: Cannot open infile %s\n",argv);
  930. fflush(stdout);
  931. exit(1);
  932. }
  933. if(stringstoresize == 0) {
  934. if((stringstore = (char *)exmalloc(total_space))==NULL) {
  935. sprintf(errstr,"Out of Memory\n");
  936. do_error();
  937. }
  938. }
  939. while(fgets(temp,200,fp[0])!=NULL) {
  940. p = temp;
  941. cccnt = 0;
  942. while(strgetstr(&p,temp2)) {
  943. strspace = strlen(temp2)+1;
  944. old_stringstoresize = stringstoresize;
  945. if((stringstoresize += strspace) >= total_space) {
  946. while(stringstoresize >= total_space)
  947. total_space += space_step;
  948. if((zong = (char *)malloc(total_space))==NULL) {
  949. sprintf(errstr,"Out of Memory\n");
  950. do_error();
  951. }
  952. memcpy(zong,stringstore,old_stringstoresize);
  953. free(stringstore);
  954. stringstore = zong;
  955. }
  956. strcpy(stringstore + stringstart,temp2);
  957. stringstart += strspace;
  958. stringscnt++;
  959. cccnt++;
  960. }
  961. if(lcnt == 0) {
  962. ccnt = cccnt;
  963. lcnt++;
  964. } else if(ccnt != cccnt) {
  965. if(cccnt != 0) {
  966. fprintf(stdout,"ERROR: File %s is not a true table file (line %d has %d cols instead of %d).\n",
  967. argv,lcnt+1,cccnt,ccnt);
  968. fflush(stdout);
  969. exit(1);
  970. } else {
  971. continue;
  972. }
  973. } else {
  974. lcnt++;
  975. }
  976. }
  977. if(stringscnt <= n) {
  978. fprintf(stdout,"ERROR: Invalid or missing data.\n");
  979. fflush(stdout);
  980. exit(1);
  981. }
  982. if(strings == 0) {
  983. if((strings = (char **)malloc(stringscnt * sizeof(char *)))==NULL) {
  984. sprintf(errstr,"Out of Memory\n");
  985. do_error();
  986. }
  987. } else {
  988. if((strings = (char **)realloc((char *)strings,stringscnt * sizeof(char *)))==NULL) {
  989. sprintf(errstr,"Out of Memory\n");
  990. do_error();
  991. }
  992. }
  993. p = stringstore;
  994. nn = 0;
  995. while(nn < stringscnt) {
  996. strings[nn] = p;
  997. while(*p != ENDOFSTR)
  998. p++;
  999. p++;
  1000. nn++;
  1001. }
  1002. fclose(fp[0]);
  1003. return ccnt;
  1004. }
  1005. /************************* DO_OTHER_STRINGLINE_INFILE ***************************/
  1006. void do_other_stringline_infiles(char *argv[],char c)
  1007. {
  1008. int n;
  1009. int sum, thiscolcnt, last_stringscnt, this_stringscnt, rowcnt=0, thisrowcnt;
  1010. if((cntr = (int *)malloc(infilecnt*sizeof(int)))==NULL) {
  1011. fprintf(stdout,"ERROR: Out of memory.\n");
  1012. fflush(stdout);
  1013. exit(1);
  1014. }
  1015. cntr[0] = stringscnt;
  1016. sum = cntr[0];
  1017. if(c == 'J') {
  1018. if((rowcnt = stringscnt/colcnt) * colcnt != stringscnt) {
  1019. fprintf(stdout,
  1020. "ERROR: Incomplete table 1 : all rows must have same number of columns for this option.\n");
  1021. fflush(stdout);
  1022. exit(1);
  1023. }
  1024. }
  1025. for(n=1;n<infilecnt;n++) {
  1026. last_stringscnt = stringscnt;
  1027. thiscolcnt = do_stringline_infile(argv[n+1],stringscnt);
  1028. switch(c) {
  1029. case('j'):
  1030. if(thiscolcnt != colcnt) {
  1031. fprintf(stdout,"ERROR: Count of columns incompatible in the input files.\n");
  1032. fflush(stdout);
  1033. exit(1);
  1034. }
  1035. break;
  1036. case('W'):
  1037. if(thiscolcnt != colcnt) {
  1038. fprintf(stdout,"ERROR: Count of columns incompatible in the input files.\n");
  1039. fflush(stdout);
  1040. exit(1);
  1041. }
  1042. break;
  1043. case('J'):
  1044. this_stringscnt = stringscnt - last_stringscnt;
  1045. if((thisrowcnt = this_stringscnt/thiscolcnt) * thiscolcnt != this_stringscnt) {
  1046. fprintf(stdout,
  1047. "ERROR: Table %d incomplete: all rows must have same number of columns for this option.\n",n+1);
  1048. fflush(stdout);
  1049. exit(1);
  1050. }
  1051. if(thisrowcnt != rowcnt) {
  1052. fprintf(stdout,"ERROR: File %d does not have same number of rows as 1st file.\n",n+1);
  1053. fflush(stdout);
  1054. exit(1);
  1055. }
  1056. break;
  1057. }
  1058. cntr[n] = stringscnt - sum;
  1059. sum += cntr[n];
  1060. }
  1061. if(c == 'J')
  1062. colcnt = rowcnt; /* held temporarily in global */
  1063. }
  1064. /************************* DO_STRING_INFILE ***************************/
  1065. void do_string_infile(char *argv)
  1066. {
  1067. int strspace;
  1068. int space_step = 200, startstringscnt = stringscnt, n;
  1069. //int old_stringstoresize;
  1070. char *p;
  1071. char temp2[200];
  1072. int total_space = space_step;
  1073. if((fp[0] = fopen(argv,"r"))==NULL) {
  1074. sprintf(errstr,"Cannot open infile %s\n",argv);
  1075. do_error();
  1076. }
  1077. if(stringstoresize == 0) {
  1078. if((stringstore = (char *)malloc(total_space))==NULL) {
  1079. sprintf(errstr,"Out of Memory\n");
  1080. do_error();
  1081. }
  1082. }
  1083. while(fgets(temp,200,fp[0])!=NULL) {
  1084. p = temp;
  1085. while(strgetstr(&p,temp2)) {
  1086. strspace = strlen(temp2)+1;
  1087. //old_stringstoresize = stringstoresize;
  1088. if((stringstoresize += strspace) >= total_space) {
  1089. while(stringstoresize >= total_space)
  1090. total_space += space_step;
  1091. if((stringstore = (char *)realloc((char *)stringstore,total_space))==NULL) {
  1092. sprintf(errstr,"Out of Memory\n");
  1093. do_error();
  1094. }
  1095. }
  1096. strcpy(stringstore + stringstart,temp2);
  1097. stringstart += strspace;
  1098. stringscnt++;
  1099. }
  1100. }
  1101. if(stringscnt <=0) {
  1102. sprintf(errstr,"Invalid or missing data.\n");
  1103. do_error();
  1104. }
  1105. if(strings == 0) {
  1106. if((strings = (char **)malloc(stringscnt * sizeof(char *)))==NULL) {
  1107. sprintf(errstr,"Out of Memory\n");
  1108. do_error();
  1109. }
  1110. } else {
  1111. if((strings = (char **)realloc((char *)strings,stringscnt * sizeof(char *)))==NULL) {
  1112. sprintf(errstr,"Out of Memory\n");
  1113. do_error();
  1114. }
  1115. }
  1116. p = stringstore;
  1117. n = 0;
  1118. while(n < startstringscnt) {
  1119. while(*p != ENDOFSTR)
  1120. p++;
  1121. p++;
  1122. n++;
  1123. }
  1124. while(n < stringscnt) {
  1125. strings[n] = p;
  1126. while(*p != ENDOFSTR)
  1127. p++;
  1128. p++;
  1129. n++;
  1130. }
  1131. fclose(fp[0]);
  1132. }
  1133. /************************* TEST_WARP_DATA ***************************/
  1134. void test_warp_data(void)
  1135. {
  1136. int n = 0;
  1137. if(number[n] < 0) {
  1138. sprintf(errstr,"Negative time in breakpoint file: Cannot proceed.\n");
  1139. do_error();
  1140. exit(1);
  1141. }
  1142. if(number[1] < 1.0/1024.0 || number[1] > 1024.0) {
  1143. sprintf(errstr,"Dubious Timestretch value (%lf) in brkpnt file.\n",number[1]);
  1144. do_error();
  1145. exit(1);
  1146. }
  1147. for(n = 2; n <firstcnt; n+=2) {
  1148. if(number[n] <= number[n-2]) {
  1149. sprintf(errstr,"Times (%lf & %lf) not in increasing order in brkpnt file.\n",number[n-2],number[n]);
  1150. do_error();
  1151. exit(1);
  1152. }
  1153. if(number[n+1] < 1.0/1024.0 || number[n+1] > 1024.0) {
  1154. sprintf(errstr,"Dubious Timestretch value (%lf) in brkpnt file.\n",number[n+1]);
  1155. do_error();
  1156. exit(1);
  1157. }
  1158. }
  1159. for(n = firstcnt; n <cnt; n++) {
  1160. if(number[n] < 0.0) {
  1161. sprintf(errstr,"Negative time (%lf) given in 2nd file: Cannot proceed.\n",number[n]);
  1162. do_error();
  1163. exit(1);
  1164. }
  1165. }
  1166. }