ts_convert.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571
  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. /*
  22. * CONVERT TIME-SERIES DATA TO A SPECIFIED RANGE (and possibly a breaktable output)
  23. */
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <math.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include <sfsys.h> //needed for max/min
  30. #define NEWLINE ('\n')
  31. #define ENDOFSTR ('\0')
  32. #define FLTERR (0.000002)
  33. #ifndef HUGE
  34. #define HUGE 3.40282347e+38F
  35. #endif
  36. const char* cdp_version = "6.1.0";
  37. //CDP LIB REPLACEMENTS
  38. static int usage();
  39. static int get_float_from_within_string(char **str,double *val);
  40. static int rround(double val);
  41. static int flteq(double f1,double f2);
  42. static double read_the_value_from_brktable(double *brk,int brksize,double time);
  43. /**************************************** MAIN *********************************************/
  44. int main(int argc,char *argv[])
  45. {
  46. char durstr[200], temp[400], fixfnam[400], *q;
  47. int isoutdur = 0, rectified = 0, logarithmic = 0, compact = 0, cutoff = 0, quantise = 0, qcompact = 0, fixed = 0, k;
  48. double *intable, *outtable, *fixtable = NULL, *p, d;
  49. double outminval, outmaxval, outrange, outdur, minstep, lastval, maxoutdur = 0.0;
  50. double inminval, inmaxval, inrange, rconvert, timestep, time, val;
  51. int inarraysize, outarraysize, fixarraysize = 0, n, t, m;
  52. double val1, val2, step;
  53. int laststep, thisstep;
  54. FILE *fp;
  55. time = 0.0;
  56. outdur = 1.0;
  57. timestep = 1.0;
  58. minstep = 0.0;
  59. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  60. fprintf(stderr,"%s\n",cdp_version);
  61. return 0;
  62. }
  63. if(argc <= 1) {
  64. usage();
  65. return 0;
  66. } else if(argc < 5 || argc > 9) {
  67. usage();
  68. return 0;
  69. }
  70. if(sscanf(argv[3],"%lf",&outminval) != 1) {
  71. fprintf(stderr, "Can'read minimum output value %s\n",argv[3]);
  72. return 0;
  73. }
  74. if(sscanf(argv[4],"%lf",&outmaxval) != 1) {
  75. fprintf(stderr, "Can'read maximum output value %s\n",argv[4]);
  76. return 0;
  77. }
  78. outrange = outmaxval - outminval;
  79. if(argc > 5) {
  80. k = 5;
  81. while(k < argc) {
  82. if(argv[k][0] == '-' && argv[k][1] == 'r')
  83. rectified = 1;
  84. else if(argv[k][0] == '-' && argv[k][1] == 'l')
  85. logarithmic = 1;
  86. else if(argv[k][0] == '-' && argv[k][1] == 'q')
  87. quantise = 1;
  88. else if(argv[k][0] == '-' && argv[k][1] == 'Q') {
  89. quantise = 1;
  90. qcompact = 1;
  91. }
  92. else {
  93. if(sscanf(argv[k],"%s",durstr) != 1) {
  94. fprintf(stderr, "Can'read flag %s\n",argv[k]); //RWD added %s
  95. return 0;
  96. }
  97. if(durstr[0] != '-') {
  98. fprintf(stderr, "Invalid flag %s\n",argv[k]);
  99. return 0;
  100. }
  101. if(durstr[1] == 'd') {
  102. if(strlen(durstr) < 3) {
  103. fprintf(stderr, "No duration value\n");
  104. return 0;
  105. }
  106. if(sscanf(&(durstr[2]),"%lf",&outdur) != 1) {
  107. fprintf(stderr, "Can't read output duration (-d)\n");
  108. return 0;
  109. }
  110. if(outdur <= 0.0) {
  111. fprintf(stderr, "Invalid output duration specified (-d).\n");
  112. return 0;
  113. }
  114. isoutdur = 1;
  115. } else if(durstr[1] == 'm') {
  116. if(strlen(durstr) < 3) {
  117. fprintf(stderr, "No maximum duration value (-m)\n");
  118. return 0;
  119. }
  120. if(sscanf(&(durstr[2]),"%lf",&maxoutdur) != 1) {
  121. fprintf(stderr, "Can'read maximum duration (-m)\n");
  122. return 0;
  123. }
  124. if(maxoutdur <= 0.0) {
  125. fprintf(stderr, "Invalid maximum duration specified (-m)\n");
  126. return 0;
  127. }
  128. cutoff = 1;
  129. } else if(durstr[1] == 'c') {
  130. if(strlen(durstr) < 3) {
  131. fprintf(stderr, "No minimum step info\n");
  132. return 0;
  133. }
  134. if(sscanf(&(durstr[2]),"%lf",&minstep) != 1) {
  135. fprintf(stderr, "Can'read minimum step\n");
  136. return 0;
  137. }
  138. if(minstep <= 0.0) {
  139. fprintf(stderr, "Invalid minimum step specified.\n");
  140. return 0;
  141. }
  142. compact = 1;
  143. } else if(durstr[1] == 'f') {
  144. if(strlen(durstr) < 3) {
  145. fprintf(stderr, "No fixed times file\n");
  146. return 0;
  147. }
  148. if(sscanf(&(durstr[2]),"%s",fixfnam) != 1) {
  149. fprintf(stderr, "Can'read filename for fixed times\n");
  150. return 0;
  151. }
  152. if((fp = fopen(fixfnam,"r"))==NULL) {
  153. fprintf(stderr, "Can't open file %s to read time data.\n",fixfnam);
  154. return 0;
  155. }
  156. while(fgets(temp,200,fp)==temp) { /* COUNT VALS */
  157. q = temp;
  158. if(*q == ';') // Allow comments in file
  159. continue;
  160. while(get_float_from_within_string(&q,&d))
  161. fixarraysize++;
  162. }
  163. if((fixtable = (double *)malloc((fixarraysize+2) * sizeof(double)))==NULL) {
  164. fprintf(stderr,"INSUFFICIENT MEMORY to store fixed time data.\n");
  165. return 0;
  166. }
  167. lastval = -1.0;
  168. p = fixtable;
  169. rewind(fp);
  170. while(fgets(temp,200,fp)==temp) { /* READ AND TEST VALS */
  171. q = temp;
  172. if(*q == ';') // Allow comments in file
  173. continue;
  174. while(get_float_from_within_string(&q,&d)) {
  175. if(d < 0.0) {
  176. fprintf(stderr,"Invalid subzero time in fixed time data.\n");
  177. fclose(fp);
  178. return 0;
  179. } else if(d <= lastval) {
  180. fprintf(stderr,"Times do not all advance in fixed time data.\n");
  181. fclose(fp);
  182. return 0;
  183. }
  184. lastval = d;
  185. *p = d;
  186. p++;
  187. }
  188. }
  189. fclose(fp);
  190. fixed = 1;
  191. } else {
  192. fprintf(stderr, "Invalid flag %s\n",argv[k]);
  193. return 0;
  194. }
  195. }
  196. k++;
  197. }
  198. }
  199. if(rectified && compact) {
  200. fprintf(stderr, "Can't specify rectification and also do compacting.\n");
  201. return 0;
  202. }
  203. if(rectified && quantise) {
  204. fprintf(stderr, "Can't specify rectification and quantisation.\n");
  205. return 0;
  206. }
  207. if(compact && quantise) {
  208. fprintf(stderr, "Can't specify compacting and quantisation.\n");
  209. return 0;
  210. }
  211. if(fixed && !isoutdur) {
  212. fprintf(stderr, "Can't specify output times without specifying output dur.\n");
  213. return 0;
  214. }
  215. if(isoutdur && compact) {
  216. fprintf(stderr, "output dur (-d) not applicable when compacting: use -m flag.\n");
  217. return 0;
  218. }
  219. if((fp = fopen(argv[1],"r"))==NULL) {
  220. fprintf(stderr, "Can't open file %s to read data.\n",argv[1]);
  221. return 0;
  222. }
  223. inarraysize = 0;
  224. while(fgets(temp,200,fp)==temp) { /* COUNT VALS */
  225. q = temp;
  226. while(get_float_from_within_string(&q,&d))
  227. inarraysize++;
  228. }
  229. if((intable = (double *)malloc((inarraysize+2) * sizeof(double)))==NULL) {
  230. fprintf(stderr,"INSUFFICIENT MEMORY to store input data.\n");
  231. return 0;
  232. }
  233. inminval = HUGE;
  234. inmaxval = -HUGE;
  235. p = intable;
  236. rewind(fp);
  237. while(fgets(temp,200,fp)==temp) { /* READ AND TEST VALS */
  238. q = temp;
  239. while(get_float_from_within_string(&q,&d)) {
  240. if(d < inminval)
  241. inminval = d;
  242. if(d > inmaxval)
  243. inmaxval = d;
  244. *p = d;
  245. p++;
  246. }
  247. }
  248. fclose(fp);
  249. inrange = inmaxval - inminval;
  250. if(inrange <= 0.0) {
  251. fprintf(stderr,"Input data does not vary: cannot proceed.\n");
  252. return 0;
  253. }
  254. rconvert = outrange/inrange;
  255. outarraysize = inarraysize;
  256. if(isoutdur) {
  257. outarraysize *= 2;
  258. timestep = outdur/(double)inarraysize;
  259. time = 0.0;
  260. }
  261. if((outtable = (double *)malloc((outarraysize+2) * sizeof(double)))==NULL) {
  262. fprintf(stderr,"INSUFFICIENT MEMORY to store output data.\n");
  263. return 0;
  264. }
  265. n = 0;
  266. if(logarithmic) {
  267. for(n=0;n < inarraysize;n++) {
  268. val = intable[n] - inminval; // Range 0 to inrange
  269. val /= inrange; // Range 0 to 1
  270. val = exp(val); // Range 1 to e
  271. val -= 1.0; // Range 0 to (e-1)
  272. intable[n] = val;
  273. }
  274. inminval = HUGE;
  275. inmaxval = -HUGE;
  276. for(n=0;n < inarraysize;n++) {
  277. inmaxval = max(intable[n],inmaxval);
  278. inminval = min(intable[n],inminval);
  279. }
  280. inrange = inmaxval - inminval;
  281. rconvert = outrange/inrange;
  282. }
  283. if(rectified) {
  284. for(n=0;n < inarraysize;n++) {
  285. val = intable[n] - inminval; // Range 0 to inrange
  286. val /= inrange; // Range 0 to 1
  287. val *= 2.0; // Range 0 to 2
  288. val -= 1.0; // Range -1 to 1
  289. intable[n] = fabs(val); // Range 0 to 1
  290. }
  291. inminval = 0.0;
  292. rconvert = outrange;
  293. }
  294. if(isoutdur) {
  295. for(n=0,t=0,m=1;n < inarraysize;n++,t+=2,m+=2) {
  296. val = intable[n] - inminval;
  297. val *= rconvert;
  298. val += outminval;
  299. outtable[t] = time;
  300. if(quantise)
  301. outtable[m] = rround(val);
  302. else
  303. outtable[m] = val;
  304. time += timestep;
  305. if(cutoff && (time > maxoutdur))
  306. break;
  307. }
  308. outarraysize = t;
  309. } else {
  310. for(n=0;n < inarraysize;n++) {
  311. val = intable[n] - inminval;
  312. val *= rconvert;
  313. val += outminval;
  314. if(quantise)
  315. outtable[n] = rround(val);
  316. else
  317. outtable[n] = val;
  318. }
  319. }
  320. if(compact) {
  321. val1 = outtable[0];
  322. val2 = outtable[1];
  323. step = val2 - val1;
  324. if(step >= 0)
  325. laststep = 1;
  326. else
  327. laststep = -1;
  328. n = 2;
  329. while(n < outarraysize) { // eliminate steps in same direction
  330. val1 = outtable[n-1];
  331. val2 = outtable[n];
  332. step = val2 - val1;
  333. if(step >= 0)
  334. thisstep = 1;
  335. else
  336. thisstep = -1;
  337. if(thisstep == laststep) {
  338. m = n;
  339. while(m <outarraysize) {
  340. outtable[m-1] = outtable[m];
  341. m++;
  342. }
  343. outarraysize--;
  344. } else {
  345. laststep = thisstep;
  346. n++;
  347. }
  348. }
  349. n = 1;
  350. while(n < outarraysize) { // eliminate too small steps
  351. val1 = outtable[n-1];
  352. val2 = outtable[n];
  353. step = val2 - val1;
  354. if(fabs(step) < minstep) {
  355. m = n + 1;
  356. if(m <outarraysize) {
  357. while(m <outarraysize) {
  358. outtable[m-1] = outtable[m];
  359. m++;
  360. }
  361. }
  362. outarraysize--;
  363. } else {
  364. n++;
  365. }
  366. }
  367. if(cutoff) {
  368. n = 1;
  369. val = 0;
  370. while(n < outarraysize) { // curtail total duration
  371. val += fabs(outtable[n] - outtable[n-1]);
  372. if(val >= outdur) {
  373. outarraysize = n + 1;
  374. break;
  375. }
  376. n++;
  377. }
  378. }
  379. } else if(qcompact) {
  380. if(isoutdur) {
  381. n = 3;
  382. while(n < outarraysize) {
  383. if(flteq(outtable[n],outtable[n-2])) {
  384. m = n;
  385. while(m < outarraysize) {
  386. outtable[m-2] = outtable[m];
  387. m++;
  388. }
  389. outarraysize -= 2;
  390. } else
  391. n += 2;
  392. }
  393. } else {
  394. n = 1;
  395. while(n < outarraysize) {
  396. if(flteq(outtable[n],outtable[n-1])) {
  397. m = n;
  398. while(m < outarraysize) {
  399. outtable[m-1] = outtable[m];
  400. m++;
  401. }
  402. outarraysize--;
  403. } else
  404. n++;
  405. }
  406. }
  407. }
  408. if(fixed) {
  409. n = 0;
  410. while(n < fixarraysize) {
  411. val = read_the_value_from_brktable(outtable,outarraysize,fixtable[n]);
  412. fixtable[n] = val;
  413. n++;
  414. }
  415. }
  416. if((fp = fopen(argv[2],"w"))==NULL) {
  417. fprintf(stderr, "Can't open file %s to write data.\n",argv[2]);
  418. return 0;
  419. }
  420. if(fixed) {
  421. for(n=0;n < fixarraysize;n++) {
  422. sprintf(temp,"%lf\n",fixtable[n]);
  423. fputs(temp,fp);
  424. }
  425. } else if(isoutdur) {
  426. for(n=0;n < outarraysize;n+=2) {
  427. sprintf(temp,"%lf %lf\n",outtable[n],outtable[n+1]);
  428. fputs(temp,fp);
  429. }
  430. } else {
  431. for(n=0;n < outarraysize;n++) {
  432. sprintf(temp,"%lf\n",outtable[n]);
  433. fputs(temp,fp);
  434. }
  435. }
  436. fclose(fp);
  437. return(1);
  438. }
  439. /******************************** USAGE2 ********************************/
  440. int usage()
  441. {
  442. fprintf(stderr,
  443. "USAGE: tsconvert indata outdata min max [-cminstep|-r|-q|-Q] [-ddur [-ftimes]] [-mmaxoutdur] [-l]\n"
  444. "\n"
  445. "Convert input data to specified range and format.\n"
  446. "\n"
  447. "INDATA Text data as a list of numerical values.\n"
  448. "MIN Minimum value in output data values.\n"
  449. "MAX Maximum value in output data values.\n"
  450. " In minimum > maximum, data contour is inverted in output.\n"
  451. "-d Generate brkpnt file of time-val pairs, duration 'dur'\n"
  452. " thus determining the timestep between output values,\n"
  453. "-m Curtail total outlength to maximum of 'outdur'.\n"
  454. " With brkpnt outputs, values generated beyond maxoutdur are ignored.\n"
  455. " with '-c' flag, absolute size of values are summed.\n"
  456. "-c compact data, so no (absolute)value is less than minstep,\n"
  457. " and steps in same direction are joined into same step\n"
  458. "-r Rectify the data around the mean.\n"
  459. " Mean value = minimum: other vals become deviations from mean.\n"
  460. "-q Quantise the data to whole-number values only.\n"
  461. "-Q Quantise the data and suppress adjacent equal-values.\n"
  462. "-f Output (untimed) vals at times specified in 'times' file (needs -d)\n"
  463. "-l Output values vary as log of input values.\n");
  464. return 0;
  465. }
  466. /************************** GET_FLOAT_FROM_WITHIN_STRING **************************
  467. * takes a pointer TO A POINTER to a string. If it succeeds in finding
  468. * a float it returns the float value (*val), and it's new position in the
  469. * string (*str).
  470. */
  471. int get_float_from_within_string(char **str,double *val)
  472. {
  473. char *p, *valstart;
  474. int decimal_point_cnt = 0, has_digits = 0;
  475. p = *str;
  476. while(isspace(*p))
  477. p++;
  478. valstart = p;
  479. switch(*p) {
  480. case('-'): break;
  481. case('.'): decimal_point_cnt=1; break;
  482. default:
  483. if(!isdigit(*p))
  484. return 0;
  485. has_digits = 1;
  486. break;
  487. }
  488. p++;
  489. while(!isspace(*p) && *p!=NEWLINE && *p!=ENDOFSTR) {
  490. if(isdigit(*p))
  491. has_digits = 1;
  492. else if(*p == '.') {
  493. if(++decimal_point_cnt>1)
  494. return 0;
  495. } else
  496. return 0;
  497. p++;
  498. }
  499. if(!has_digits || sscanf(valstart,"%lf",val)!=1)
  500. return 0;
  501. *str = p;
  502. return 1;
  503. }
  504. /**************************** RROUND *******************************/
  505. int rround(double val)
  506. {
  507. int k;
  508. k = (int)(fabs(val)+0.5);
  509. if(val < 0.0)
  510. k = -k;
  511. return k;
  512. }
  513. /**************************** FLTEQ *******************************/
  514. int flteq(double f1,double f2)
  515. {
  516. double upperbnd, lowerbnd;
  517. upperbnd = f2 + FLTERR;
  518. lowerbnd = f2 - FLTERR;
  519. if((f1>upperbnd) || (f1<lowerbnd))
  520. return(0);
  521. return(1);
  522. }
  523. /**************************** READ_THE_VALUE_FROM_BRKTABLE *****************************/
  524. double read_the_value_from_brktable(double *brk,int brksize,double time)
  525. {
  526. int n;
  527. double lotime, loval, hitime, hival, diff, tratio, val;
  528. n = 0;
  529. while(n < brksize) {
  530. if(brk[n] >= time)
  531. break;
  532. n += 2;
  533. }
  534. if(n >= brksize)
  535. return brk[n-1];
  536. else if(n == 0)
  537. return brk[1];
  538. lotime = brk[n-2];
  539. loval = brk[n-1];
  540. hitime = brk[n];
  541. hival = brk[n+1];
  542. diff = hival - loval;
  543. tratio = (time - lotime)/(hitime - lotime);
  544. diff *= tratio;
  545. val = loval + diff;
  546. return val;
  547. }