spacedesign.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143
  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. spacedesign stom genericoutfilename convergestarttime convergeendtime convergeposition
  23. spacedesign mtos genericoutfilename divergestarttime divergeendtime divergeposition
  24. spacedesign rotate genericoutfilename starttime endtime startpos
  25. endpos edgetimes width clokwise? lingerfactor loudnessdepth loudnesslead attenuation filterfrq
  26. entry entry entry radiobuts entry entry entry entry
  27. -1 to 1 increasing time/ >0 && <1 >= 1 0 - 1 >0 to 10 ?? 10 - 10000
  28. times width dflt 1
  29. edgetimes are times at which rotation reaches extremal left or right point
  30. MUST be > starttime
  31. */
  32. #include <stdio.h>
  33. #include <stdlib.h>
  34. #include <math.h>
  35. #include <string.h>
  36. #include <ctype.h>
  37. //TW UPDATE
  38. //#include <ctype.h>
  39. /* RWD Jan 2014 corrected spelling mistoke in usage */
  40. #define ENDOFSTR ('\0')
  41. #ifndef PI
  42. #define PI (3.141592654)
  43. #endif
  44. #define LINGRATIO (0.222222222) /* 2 9ths = proprtion of space not in linger */
  45. #define FLTERR (0.000002)
  46. static void strip_file_extension(char *filename);
  47. static int stom(char *filename1,char *filename2,float starttime,float endttime,float endpos);
  48. static int mtos(char *filename1,char *filename2,float starttime,float endtime,float startpos);
  49. static void usage(int mode);
  50. static int read_rotation_data(FILE *fpr,float **rotdat);
  51. static int read_width_data(FILE *fpr,float **widdat);
  52. static int strgetfloat(char **str,double *val);
  53. static int rotate(char *fnam1,char *fnam2,char *fnam3,float starttime,float endtime,float startpos,float endpos,
  54. int clokwise,int rotcnt,float *rotdat,int widcnt,float *widdat,float linger,float depth,
  55. float lead,float atten,int isfilt,float warp);
  56. static int read_value_from_brktable(float *val,float *brk, int brksize, float thistime,int init);
  57. static int flteq(double f1,double f2);
  58. static int isnumeric(char *str);
  59. const char* cdp_version = "7.1.0";
  60. int main(int argc, char *argv[])
  61. {
  62. int mode = 0, exit_status = 1, rotcnt = 0, widcnt=0, clokwise, isfilt;
  63. float starttime, endtime, endpos, startpos=0.0f, *rotdat = NULL, *widdat = NULL, dummy;
  64. float linger, depth, lead, atten, warp;
  65. FILE *fp, *fpr, *fpw;
  66. char filename[400], filename1[400], filename2[400], filename3[400] ,errword[10], errword2[12], errword3[8];
  67. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  68. fprintf(stdout,"%s\n",cdp_version);
  69. fflush(stdout);
  70. return 0;
  71. }
  72. if(argc < 2) {
  73. usage(0);
  74. return 0;
  75. }
  76. if(!strcmp(argv[1],"stom")) {
  77. mode = 1;
  78. } else if (!strcmp(argv[1],"mtos")) {
  79. mode = 2;
  80. } else if (!strcmp(argv[1],"rotate")) {
  81. mode = 3;
  82. }
  83. switch(mode) {
  84. case(1):
  85. case(2):
  86. if(argc != 6) {
  87. usage(mode);
  88. return 0;
  89. }
  90. break;
  91. case(3):
  92. if(argc != 16) {
  93. usage(mode);
  94. return 0;
  95. }
  96. break;
  97. default:
  98. fprintf(stdout,"ERROR: Unknown mode '%s': spacedesign()\n",argv[1]);
  99. fflush(stdout);
  100. return 0;
  101. }
  102. switch(mode) {
  103. case(1): strcpy(errword,"converge"); strcpy(errword2,"end"); strcpy(errword3,"stom"); break;
  104. case(2): strcpy(errword,"diverge"); strcpy(errword2,"start"); strcpy(errword3,"mtos"); break;
  105. case(3): strcpy(errword,"rotate"); strcpy(errword2,"start"); strcpy(errword3,"rotate"); break;
  106. }
  107. switch(mode) {
  108. case(1):
  109. case(2):
  110. case(3):
  111. if(sscanf(argv[2],"%s",filename)!=1) {
  112. fprintf(stdout,"ERROR: Failed to read outfilename: spacedesign\n");
  113. fflush(stdout);
  114. return 0;
  115. }
  116. if(sscanf(argv[3],"%f",&starttime)!=1 || starttime < 0.0) {
  117. fprintf(stdout,"ERROR: bad %s starttime parameter: spacedesign %s\n",errword,errword3);
  118. fflush(stdout);
  119. return 0;
  120. }
  121. if(sscanf(argv[4],"%f",&endtime)!=1 || endtime <= starttime) {
  122. fprintf(stdout,"ERROR: bad %s endtime parameter: spacedesign %s\n",errword,errword3);
  123. fflush(stdout);
  124. return 0;
  125. }
  126. if(sscanf(argv[5],"%f",&endpos)!=1 || (endpos < -1.0 || endpos > 1.0)) {
  127. fprintf(stdout,"ERROR: bad %s %s position parameter: spacedesign %s\n",errword,errword2,errword3);
  128. fflush(stdout);
  129. return 0;
  130. }
  131. if(mode==2 || mode==3)
  132. startpos = endpos;
  133. break;
  134. }
  135. switch(mode) {
  136. case(1):
  137. case(2):
  138. case(3):
  139. strip_file_extension(filename);
  140. strcpy(filename1,filename);
  141. strcat(filename1,"1");
  142. strcat(filename1,".txt");
  143. strcpy(filename2,filename);
  144. strcat(filename2,"2");
  145. strcat(filename2,".txt");
  146. strcpy(filename3,filename);
  147. strcat(filename3,"3");
  148. strcat(filename3,".txt");
  149. if((fp = fopen(filename1,"r"))!=NULL) {
  150. fprintf(stdout,"ERROR: file %s already exists: spacedesign()\n",filename1);
  151. fclose(fp);
  152. fflush(stdout);
  153. return 0;
  154. }
  155. if((fp = fopen(filename2,"r"))!=NULL) {
  156. fprintf(stdout,"ERROR: file %s already exists: spacedesign()\n",filename2);
  157. fclose(fp);
  158. fflush(stdout);
  159. return 0;
  160. }
  161. break;
  162. }
  163. switch(mode) {
  164. case(3):
  165. if(sscanf(argv[6],"%f",&endpos)!=1 || (endpos < -1.0 || endpos > 1.0)) {
  166. fprintf(stdout,"ERROR: bad end position parameter: spacedesign %s\n",errword3);
  167. fflush(stdout);
  168. return 0;
  169. }
  170. if((fpr = fopen(argv[7],"r"))==NULL) {
  171. fprintf(stdout,"ERROR: Bad edgetimes data: spacedesign %s\n",errword3);
  172. fflush(stdout);
  173. return 0;
  174. }
  175. if((rotcnt = read_rotation_data(fpr,&rotdat))<=0)
  176. return 0;
  177. if(*rotdat <= starttime) {
  178. fprintf(stdout,"ERROR: First edgetime <= rotation starttime: spacedesign %s\n",errword3);
  179. fflush(stdout);
  180. return 0;
  181. }
  182. if(isnumeric(argv[8])) {
  183. sscanf(argv[8],"%f",&dummy);
  184. if (dummy < 0.0 || dummy > 1.0) {
  185. fprintf(stdout,"ERROR: Bad width value (range 0 - 1): spacedesign %s\n",errword3);
  186. fflush(stdout);
  187. return 0;
  188. }
  189. widcnt = 1;
  190. if((widdat = (float *)malloc(4 * sizeof(float)))==NULL) {
  191. fprintf(stdout,"ERROR: Cannot allocate memory for width data: spacedesign %s\n",errword3);
  192. fflush(stdout);
  193. return 0;
  194. }
  195. *widdat = 0.0f;
  196. *(widdat+1) = dummy;
  197. *(widdat+2) = 10000.0f;
  198. *(widdat+3) = dummy;
  199. } else if((fpw = fopen(argv[8],"r"))==NULL) {
  200. fprintf(stdout,"ERROR: Bad width data: spacedesign %s\n",errword3);
  201. fflush(stdout);
  202. return 0;
  203. } else if((widcnt = read_width_data(fpw,&widdat))<=0)
  204. return 0;
  205. if(sscanf(argv[9],"%d",&clokwise)!=1 || (clokwise != 1 && clokwise != 0)) {
  206. fprintf(stdout,"ERROR: bad direction value: 1 for clockwise, 0 for anticlockwise\n");
  207. fflush(stdout);
  208. return 0;
  209. }
  210. if(sscanf(argv[10],"%f",&linger)!=1 || linger >= 1.0 || linger <= 0.0) {
  211. fprintf(stdout,"ERROR: bad linger value: range >0 to <1\n");
  212. fflush(stdout);
  213. return 0;
  214. }
  215. if(sscanf(argv[11],"%f",&depth)!=1 || depth < 1.0) {
  216. fprintf(stdout,"ERROR: bad depth value: must be >= 1\n");
  217. fflush(stdout);
  218. return 0;
  219. }
  220. if(sscanf(argv[12],"%f",&lead)!=1 || lead < 0.0 || lead > 1.0) {
  221. fprintf(stdout,"ERROR: bad lead value: range 0-1\n");
  222. fflush(stdout);
  223. return 0;
  224. }
  225. if(sscanf(argv[13],"%f",&atten)!=1 || atten <= 0.0 || atten >= 10) {
  226. fprintf(stdout,"ERROR: bad attenuation value: range >0-10\n");
  227. fflush(stdout);
  228. return 0;
  229. }
  230. if(sscanf(argv[14],"%d",&isfilt)!=1 || (isfilt != 0 && isfilt != 1)) {
  231. fprintf(stdout,"ERROR: bad filter flag (%d)\n",isfilt);
  232. fflush(stdout);
  233. return 0;
  234. }
  235. if(isfilt) {
  236. if((fp = fopen(filename3,"r"))!=NULL) {
  237. fprintf(stdout,"ERROR: file %s already exists: spacedesign()\n",filename3);
  238. fclose(fp);
  239. fflush(stdout);
  240. return 0;
  241. }
  242. }
  243. if((sscanf(argv[15],"%f",&warp)!=1) || warp < 1 || warp > 20) {
  244. fprintf(stdout,"ERROR: bad warp value (%f)\n",warp);
  245. fflush(stdout);
  246. return 0;
  247. }
  248. break;
  249. }
  250. switch(mode) {
  251. case(1):
  252. exit_status = stom(filename1,filename2,starttime,endtime,endpos);
  253. break;
  254. case(2):
  255. exit_status = mtos(filename1,filename2,starttime,endtime,startpos);
  256. break;
  257. case(3):
  258. exit_status =
  259. rotate(filename1,filename2,filename3,starttime,endtime,startpos,endpos,clokwise,rotcnt,rotdat,
  260. widcnt,widdat,linger,depth,lead,atten,isfilt,warp);
  261. break;
  262. }
  263. return exit_status;
  264. }
  265. int stom(char *filename1,char *filename2,float starttime,float endtime,float endpos)
  266. {
  267. FILE *fp1, *fp2;
  268. char valstr[400];
  269. int OK = 1, n;
  270. double gap, step, q;
  271. double leftmove, rightmove, cospos, leftpos, rightpos, thistime;
  272. if((fp1 = fopen(filename1,"w"))==NULL) {
  273. fprintf(stdout,"ERROR: Cannot open file %s: spacedesign()\n",filename1);
  274. fflush(stdout);
  275. return -1;
  276. }
  277. if((fp2 = fopen(filename2,"w"))==NULL) {
  278. fprintf(stdout,"ERROR: Cannot open file %s: spacedesign()\n",filename2);
  279. fclose(fp1);
  280. if(remove(filename1)<0)
  281. fprintf(stdout, "ERROR: Can't remove file %s.\n",filename1);
  282. fflush(stdout);
  283. return -1;
  284. }
  285. while(OK) {
  286. strcpy(valstr,"0.0 -1.0\n");
  287. if(fputs(valstr,fp1)<0) {
  288. OK = 0;
  289. break;
  290. }
  291. strcpy(valstr,"0.0 1.0\n");
  292. if(fputs(valstr,fp2)<0) {
  293. OK = 0;
  294. break;
  295. }
  296. if(starttime > 0.0) {
  297. sprintf(valstr,"%f",starttime);
  298. strcat(valstr," -1.0\n");
  299. if(fputs(valstr,fp1)<0) {
  300. OK = 0;
  301. break;
  302. }
  303. sprintf(valstr,"%f",starttime);
  304. strcat(valstr," 1.0\n");
  305. if(fputs(valstr,fp2)<0) {
  306. OK = 0;
  307. break;
  308. }
  309. }
  310. gap = endtime - starttime;
  311. leftmove = endpos + 1.0;
  312. rightmove = endpos - 1.0;
  313. step = gap/8.0;
  314. thistime = starttime;
  315. for(n=1; n<8;n++) {
  316. thistime += step;
  317. q = (double)n/8.0;
  318. cospos = cos(q * PI);
  319. cospos = (1 - cospos)/2.0;
  320. // weight the cosinus with the straight line, to make curve less abrupt
  321. cospos = (q + (2.0 * cospos)) / 3.0;
  322. leftpos = (cospos * leftmove) - 1.0;
  323. rightpos = (cospos * rightmove) + 1.0;
  324. sprintf(valstr,"%f %f\n",thistime,(float)leftpos);
  325. if(fputs(valstr,fp1)<0) {
  326. OK = 0;
  327. break;
  328. }
  329. sprintf(valstr,"%f %f\n",thistime,(float)rightpos);
  330. if(fputs(valstr,fp2)<0) {
  331. OK = 0;
  332. break;
  333. }
  334. }
  335. if(!OK)
  336. break;
  337. sprintf(valstr,"%f %f\n",endtime,endpos);
  338. if(fputs(valstr,fp1)<0) {
  339. OK = 0;
  340. break;
  341. }
  342. if(fputs(valstr,fp2)<0) {
  343. OK = 0;
  344. break;
  345. }
  346. sprintf(valstr,"10000 %f\n",endpos);
  347. if(fputs(valstr,fp1)<0) {
  348. OK = 0;
  349. break;
  350. }
  351. if(fputs(valstr,fp2)<0)
  352. OK = 0;
  353. break;
  354. }
  355. fclose(fp1);
  356. fclose(fp2);
  357. if(!OK) {
  358. if(remove(filename1)<0)
  359. fprintf(stdout, "ERROR: Can't remove file %s.\n",filename1);
  360. if(remove(filename2)<0)
  361. fprintf(stdout, "ERROR: Can't remove file %s.\n",filename2);
  362. fflush(stdout);
  363. return 0;
  364. }
  365. return 1;
  366. }
  367. int mtos(char *filename1,char *filename2,float starttime,float endtime,float startpos)
  368. {
  369. FILE *fp1, *fp2;
  370. char valstr[400];
  371. int OK = 1, n;
  372. double gap, step, q;
  373. double leftmove, rightmove, cospos, leftpos, rightpos, thistime;
  374. if((fp1 = fopen(filename1,"w"))==NULL) {
  375. fprintf(stdout,"ERROR: Cannot open file %s: spacedesign()\n",filename1);
  376. fflush(stdout);
  377. return -1;
  378. }
  379. if((fp2 = fopen(filename2,"w"))==NULL) {
  380. fprintf(stdout,"ERROR: Cannot open file %s: spacedesign()\n",filename2);
  381. fclose(fp1);
  382. if(remove(filename1)<0)
  383. fprintf(stdout, "ERROR: Can't remove file %s.\n",filename1);
  384. fflush(stdout);
  385. return -1;
  386. }
  387. while(OK) {
  388. sprintf(valstr,"0.0 %f\n",startpos);
  389. if(fputs(valstr,fp1)<0) {
  390. OK = 0;
  391. break;
  392. }
  393. if(fputs(valstr,fp2)<0) {
  394. OK = 0;
  395. break;
  396. }
  397. if(starttime > 0.0) {
  398. sprintf(valstr,"%f %f\n",starttime,startpos);
  399. if(fputs(valstr,fp1)<0) {
  400. OK = 0;
  401. break;
  402. }
  403. if(fputs(valstr,fp2)<0) {
  404. OK = 0;
  405. break;
  406. }
  407. }
  408. gap = endtime - starttime;
  409. leftmove = -(1.0 + startpos);
  410. rightmove = 1.0 - startpos;
  411. step = gap/8.0;
  412. thistime = starttime;
  413. for(n=1; n<8;n++) {
  414. thistime += step;
  415. q = (double)n/8.0;
  416. cospos = cos(q * PI);
  417. cospos = (1 - cospos)/2.0;
  418. // weight the cosinus with the straight line, to make curve less abrupt
  419. cospos = (q + (2.0 * cospos)) / 3.0;
  420. leftpos = (cospos * leftmove) + startpos;
  421. rightpos = (cospos * rightmove) + startpos;
  422. sprintf(valstr,"%f %f\n",thistime,(float)leftpos);
  423. if(fputs(valstr,fp1)<0) {
  424. OK = 0;
  425. break;
  426. }
  427. sprintf(valstr,"%f %f\n",thistime,(float)rightpos);
  428. if(fputs(valstr,fp2)<0) {
  429. OK = 0;
  430. break;
  431. }
  432. }
  433. sprintf(valstr,"%f -1.0\n",endtime);
  434. if(fputs(valstr,fp1)<0) {
  435. OK = 0;
  436. break;
  437. }
  438. sprintf(valstr,"%f 1.0\n",endtime);
  439. if(fputs(valstr,fp2)<0) {
  440. OK = 0;
  441. break;
  442. }
  443. sprintf(valstr,"10000 -1\n");
  444. if(fputs(valstr,fp1)<0) {
  445. OK = 0;
  446. break;
  447. }
  448. sprintf(valstr,"10000 1\n");
  449. if(fputs(valstr,fp2)<0)
  450. OK = 0;
  451. break;
  452. }
  453. fclose(fp1);
  454. fclose(fp2);
  455. if(!OK) {
  456. if(remove(filename1)<0)
  457. fprintf(stdout, "ERROR: Can't remove file %s.\n",filename1);
  458. if(remove(filename2)<0)
  459. fprintf(stdout, "ERROR: Can't remove file %s.\n",filename2);
  460. fflush(stdout);
  461. return 0;
  462. }
  463. return 1;
  464. }
  465. int rotate(char *fnam1,char *fnam2,char *fnam3,float starttime,float endtime,float startpos,float endpos,int clokwise,
  466. int rotcnt,float *rotdat,int widcnt,float *widdat,float linger,float depth,float lead,float atten,int isfilt,float warp)
  467. {
  468. FILE *fp1, *fp2 ,*fp3=NULL;
  469. char valstr[200];
  470. int init = 0, n, OK = 1, right=0, doit;
  471. float width, *p, edgetime, last_edgetime, val[8];
  472. float depdiff = (float)((depth - 1.0)/(depth + 1.0));
  473. float last_edgepos, edgepos, postlingpos, prelingpos, postlingtime, prelingtime, leadval, midtime;
  474. double lingwidth, timestep, lingstep, leadstep, leadtime, frontwarp=0.0, rearwarp=0.0, step;
  475. double newtimestep, time_extend, timeratio, thisgap, newlen;
  476. int rightwards, iswarp, k;
  477. if(flteq(warp,1.0))
  478. iswarp = 0;
  479. else {
  480. iswarp = 1;
  481. frontwarp = 2.0/(double)(warp + 1.0);
  482. rearwarp = (2.0 * warp)/(double)(warp + 1.0);
  483. }
  484. if((fp1 = fopen(fnam1,"w"))==NULL) {
  485. fprintf(stdout,"ERROR: Cannot open file %s to write space data: spacedesign()\n",fnam1);
  486. fflush(stdout);
  487. return 0;
  488. }
  489. if((fp2 = fopen(fnam2,"w"))==NULL) {
  490. fprintf(stdout,"ERROR: Cannot open file %s to write loudness data: spacedesign()\n",fnam2);
  491. fflush(stdout);
  492. fclose(fp1);
  493. if(remove(fnam1)<0)
  494. fprintf(stdout, "ERROR: Can't remove file %s.\n",fnam1);
  495. fflush(stdout);
  496. return 0;
  497. }
  498. if(isfilt) {
  499. if((fp3 = fopen(fnam3,"w"))==NULL) {
  500. fprintf(stdout,"ERROR: Cannot open file %s to write loudness data: spacedesign()\n",fnam3);
  501. fflush(stdout);
  502. fclose(fp1);
  503. if(remove(fnam1)<0)
  504. fprintf(stdout, "ERROR: Can't remove file %s.\n",fnam1);
  505. fflush(stdout);
  506. fclose(fp2);
  507. if(remove(fnam2)<0)
  508. fprintf(stdout, "ERROR: Can't remove file %s.\n",fnam2);
  509. fflush(stdout);
  510. return 0;
  511. }
  512. }
  513. while(OK) {
  514. sprintf(valstr,"0.0 %f\n",atten);
  515. if(fputs(valstr,fp2)<0) {
  516. OK = 0;
  517. break;
  518. }
  519. if(isfilt) {
  520. sprintf(valstr,"0.0 1.0\n");
  521. if(fputs(valstr,fp3)<0) {
  522. OK = 0;
  523. break;
  524. }
  525. }
  526. sprintf(valstr,"0.0 %f\n",startpos);
  527. val[0] = 0.0f;
  528. val[1] = startpos;
  529. if(starttime > 0.0) {
  530. if(fputs(valstr,fp1)<0) {
  531. OK = 0;
  532. break;
  533. }
  534. val[0] = starttime;
  535. val[1] = startpos;
  536. sprintf(valstr,"%f %f\n",starttime,atten);
  537. if(fputs(valstr,fp2)<0) {
  538. OK = 0;
  539. break;
  540. }
  541. if(isfilt) {
  542. sprintf(valstr,"%f 1.0\n",starttime);
  543. if(fputs(valstr,fp3)<0) {
  544. OK = 0;
  545. break;
  546. }
  547. }
  548. }
  549. n = 0;
  550. p = rotdat;
  551. edgetime = *p;
  552. last_edgetime = starttime;
  553. last_edgepos = startpos;
  554. while(edgetime < endtime) {
  555. if(edgetime > starttime) {
  556. init = read_value_from_brktable(&width,widdat,widcnt,edgetime,init);
  557. edgepos = width;
  558. if(n==0) {
  559. if(clokwise) {
  560. edgepos = -edgepos;
  561. right = 0;
  562. } else
  563. right = 1;
  564. } else if(right) {
  565. edgepos = -edgepos;
  566. right = 0;
  567. } else
  568. right = 1;
  569. width = edgepos - last_edgepos; /* find width of pan from last edgepos */
  570. lingwidth = (width * LINGRATIO)/2.0; /* find proprtion of width taken up by each linger */
  571. postlingpos = (float)(last_edgepos + lingwidth); /* find position at end of linger after last edgepos */
  572. prelingpos = (float)(edgepos - lingwidth); /* find position at start of linger before next edgepos */
  573. timestep = edgetime - last_edgetime; /* find timestep from edge to edge */
  574. lingstep = (timestep * linger)/2.0; /* find proprtion of time used in each linger */
  575. postlingtime = (float)(last_edgetime + lingstep); /* find time of end of linger after last edgepos */
  576. prelingtime = (float)(edgetime - lingstep); /* find time of start of linger before next edgepos */
  577. midtime = (float)((edgetime + last_edgetime)/2.0);
  578. sprintf(valstr,"%f %f\n",postlingtime,postlingpos);
  579. val[2] = postlingtime;
  580. val[3] = postlingpos;
  581. val[4] = prelingtime;
  582. val[5] = prelingpos;
  583. val[6] = edgetime;
  584. val[7] = edgepos;
  585. leadstep = (timestep/2.0) * lead; /* find time to maxmin val within 1st half of timestep */
  586. leadtime = last_edgetime + leadstep; /* find time of maxmin */
  587. rightwards = 0;
  588. if(edgepos > last_edgepos) /* is soundmoving left or right */
  589. rightwards = 1;
  590. if(flteq(last_edgetime,starttime)) {
  591. leadval = atten;
  592. sprintf(valstr,"%f %f\n",midtime,leadval);
  593. } else {
  594. if(rightwards == clokwise) { /* assign min or max according to clokwise/anti */
  595. leadval = (float)(atten * (1.0 - depdiff));
  596. sprintf(valstr,"%f %f\n",midtime,leadval);
  597. } else {
  598. leadval = (float)(atten * (1.0 + depdiff));
  599. sprintf(valstr,"%f %f\n",leadtime,leadval);
  600. }
  601. }
  602. if(fputs(valstr,fp2)<0) {
  603. OK = 0;
  604. break;
  605. }
  606. if(rightwards == clokwise) {
  607. if (iswarp) {
  608. k = 2;
  609. if(flteq(last_edgetime,starttime)) { /* adjust initial set */
  610. newtimestep = timestep * rearwarp;
  611. time_extend = (newtimestep - timestep)/2.0;
  612. newtimestep = timestep + time_extend;
  613. timeratio = newtimestep/timestep;
  614. while(k < 6) {
  615. thisgap = val[k] - last_edgetime;
  616. thisgap *= timeratio;
  617. val[k] = (float)(last_edgetime + thisgap);
  618. k += 2;
  619. }
  620. } else {
  621. while(k < 6) { /* for rear motion, adjust two linger times */
  622. step = midtime - val[k];
  623. step *= rearwarp;
  624. val[k] = (float)(midtime - step);
  625. k += 2;
  626. }
  627. }
  628. }
  629. for(k=2;k<6;k+=2) {
  630. sprintf(valstr,"%f %f\n",val[k],val[k+1]);
  631. if(fputs(valstr,fp1)<0) {
  632. OK = 0;
  633. break;
  634. }
  635. }
  636. } else {
  637. if (iswarp) {
  638. k = 0;
  639. while(k < 8) { /* for front motion, adjust four linger times */
  640. step = midtime - val[k];
  641. step *= frontwarp;
  642. val[k] = (float)(midtime - step);
  643. k += 2;
  644. }
  645. if(flteq(last_edgetime,starttime)) { /* adjust initial set */
  646. step = val[0] - last_edgetime;
  647. for(k=0;k<8;k+=2)
  648. val[k] = (float)(val[k] - step);
  649. newlen = val[6] - val[0];
  650. timeratio = (newlen + step)/newlen;
  651. for(k=0;k<8;k+=2) {
  652. thisgap = val[k] - last_edgetime;
  653. thisgap *= timeratio;
  654. val[k] = (float)(last_edgetime + thisgap);
  655. }
  656. }
  657. }
  658. for(k=0;k<8;k+=2) {
  659. sprintf(valstr,"%f %f\n",val[k],val[k+1]);
  660. if(fputs(valstr,fp1)<0) {
  661. OK = 0;
  662. break;
  663. }
  664. }
  665. }
  666. if(OK == 0)
  667. break;
  668. if(isfilt) {
  669. doit = 0;
  670. if(flteq(last_edgetime,starttime)) { /* at startup, no level changes */
  671. if(!flteq(leadtime,last_edgetime)) {
  672. sprintf(valstr,"%f 1.0\n",leadtime);
  673. doit = 1;
  674. }
  675. } else if(rightwards == clokwise) { /* if different , filter in middle */
  676. sprintf(valstr,"%f 0.0\n",midtime);
  677. doit = 1;
  678. } else {
  679. sprintf(valstr,"%f 1.0\n",leadtime); /* if close, filter off at max-level point */
  680. doit = 1;
  681. }
  682. if(doit) {
  683. if(fputs(valstr,fp3)<0) {
  684. OK = 0;
  685. break;
  686. }
  687. }
  688. }
  689. last_edgetime = edgetime;
  690. last_edgepos = edgepos;
  691. }
  692. if(++n >= rotcnt)
  693. break;
  694. p++;
  695. edgetime = *p;
  696. val[0] = last_edgetime;
  697. val[1] = last_edgepos;
  698. }
  699. if(!OK)
  700. break;
  701. if((last_edgetime < endtime) && !flteq((double)endtime,(double)last_edgetime)) {
  702. edgetime = endtime;
  703. edgepos = endpos; /* convert with 0-1 --> position cal -1 to 1 */
  704. rightwards = 0;
  705. if(edgepos > last_edgepos)
  706. rightwards = 1;
  707. if(rightwards == clokwise) {
  708. last_edgetime = val[6];
  709. } else {
  710. midtime = (float)((edgetime + last_edgetime)/2.0);
  711. step = midtime - last_edgetime;
  712. if(iswarp)
  713. step *= frontwarp;
  714. last_edgetime = (float)(last_edgetime + step);
  715. if(last_edgetime >= edgetime) {
  716. OK = 0;
  717. } else {
  718. val[0] = last_edgetime;
  719. val[1] = last_edgepos;
  720. }
  721. }
  722. if(OK) {
  723. width = edgepos - last_edgepos; /* find width of pan from last TRUE edgepos */
  724. lingwidth = (width * LINGRATIO)/2.0; /* find proprtion of width taken up by each linger */
  725. postlingpos = (float)(last_edgepos + lingwidth); /* find position at end of linger after last edgepos */
  726. prelingpos = (float)(edgepos - lingwidth); /* find position at start of linger before next edgepos */
  727. timestep = edgetime - last_edgetime; /* find timestep from edge to edge */
  728. lingstep = (timestep * linger)/2.0; /* find proprtion of time used in each linger */
  729. postlingtime = (float)(last_edgetime + lingstep); /* find time of end of linger after last edgepos */
  730. prelingtime = (float)(edgetime - lingstep); /* find time of start of linger before next edgepos */
  731. val[2] = postlingtime;
  732. val[3] = postlingpos;
  733. val[4] = prelingtime;
  734. val[5] = prelingpos;
  735. val[6] = edgetime;
  736. val[7] = edgepos;
  737. if(rightwards == clokwise) {
  738. for(k=2;k<8;k+=2) {
  739. sprintf(valstr,"%f %f\n",val[k],val[k+1]);
  740. if(fputs(valstr,fp1)<0) {
  741. OK = 0;
  742. break;
  743. }
  744. }
  745. } else {
  746. for(k=0;k<8;k+=2) {
  747. sprintf(valstr,"%f %f\n",val[k],val[k+1]);
  748. if(fputs(valstr,fp1)<0) {
  749. OK = 0;
  750. break;
  751. }
  752. }
  753. }
  754. if(OK == 0)
  755. break;
  756. leadstep = (timestep/2.0) * lead; /* find time to maxmin val within 1st half of timestep */
  757. leadtime = last_edgetime + leadstep; /* find time of maxmin */
  758. sprintf(valstr,"%f %f\n",leadtime,atten);
  759. if(fputs(valstr,fp2)<0) {
  760. OK = 0;
  761. break;
  762. }
  763. if(isfilt) {
  764. if(!flteq(leadtime,last_edgetime)) {
  765. sprintf(valstr,"%f 1.0\n",leadtime);
  766. if(fputs(valstr,fp3)<0) {
  767. OK = 0;
  768. break;
  769. }
  770. }
  771. }
  772. }
  773. }
  774. sprintf(valstr,"10000 %f\n",endpos);
  775. if(fputs(valstr,fp1)<0) {
  776. OK = 0;
  777. break;
  778. }
  779. sprintf(valstr,"10000 %f\n",atten);
  780. if(fputs(valstr,fp2)<0) {
  781. OK = 0;
  782. break;
  783. }
  784. if(isfilt) {
  785. sprintf(valstr,"10000 1.0\n");
  786. if(fputs(valstr,fp3)<0) {
  787. OK = 0;
  788. break;
  789. }
  790. }
  791. break;
  792. }
  793. fclose(fp1);
  794. fclose(fp2);
  795. if(isfilt)
  796. fclose(fp3);
  797. if(!OK) {
  798. if(remove(fnam1)<0)
  799. fprintf(stdout, "ERROR: Can't remove file %s.\n",fnam1);
  800. if(remove(fnam2)<0)
  801. fprintf(stdout, "ERROR: Can't remove file %s.\n",fnam2);
  802. if(isfilt) {
  803. if(remove(fnam3)<0)
  804. fprintf(stdout, "ERROR: Can't remove file %s.\n",fnam3);
  805. }
  806. fflush(stdout);
  807. return 0;
  808. }
  809. return 1;
  810. }
  811. void strip_file_extension(char *filename)
  812. {
  813. char *p = filename;
  814. while(*p != ENDOFSTR) {
  815. if(*p == '.') {
  816. *p = ENDOFSTR;
  817. return;
  818. }
  819. p++;
  820. }
  821. return;
  822. }
  823. int read_rotation_data(FILE *fpr,float **rotdat)
  824. {
  825. char *q, temp[200];
  826. float *p;
  827. double d;
  828. double lasttime = -1.0;
  829. int arraysize = 100, n = 0;
  830. if((*rotdat = (float *)malloc(arraysize * sizeof(float)))==NULL) {
  831. fprintf(stdout,"ERROR: Insufficient memory to store rotation data\n");
  832. fflush(stdout);
  833. return -1;
  834. }
  835. p = *rotdat;
  836. while(fgets(temp,200,fpr)==temp) {
  837. q = temp;
  838. while(strgetfloat(&q,&d)) {
  839. if(d <= lasttime) {
  840. fprintf(stdout,"ERROR: Times not increasing (at %lf) in rotation data file\n",d);
  841. fflush(stdout);
  842. return -1;
  843. }
  844. lasttime = d;
  845. *p = (float)d;
  846. p++;
  847. n++;
  848. if(n >= arraysize) {
  849. arraysize += 100;
  850. if((*rotdat = (float *)realloc((char *)(*rotdat),arraysize * sizeof(float)))==NULL) {
  851. fprintf(stdout,"ERROR: Insufficient memory to expand store of rotation data\n");
  852. fflush(stdout);
  853. return -1;
  854. }
  855. }
  856. }
  857. }
  858. return n;
  859. }
  860. int read_width_data(FILE *fpr,float **widdat)
  861. {
  862. char *q, temp[200];
  863. float *p;
  864. double d;
  865. double lasttime = -1.0;
  866. int istime = 1;
  867. int arraysize = 100, n = 0;
  868. if((*widdat = (float *)malloc(arraysize * sizeof(float)))==NULL) {
  869. fprintf(stdout,"ERROR: Insufficient memory to store rotation data\n");
  870. fflush(stdout);
  871. return -1;
  872. }
  873. p = *widdat;
  874. while(fgets(temp,200,fpr)==temp) {
  875. q = temp;
  876. while(strgetfloat(&q,&d)) {
  877. switch(istime) {
  878. case(1):
  879. if(d <= lasttime) {
  880. fprintf(stdout,"ERROR: Times not increasing (at %lf) in rotation data file\n",d);
  881. fflush(stdout);
  882. return -1;
  883. }
  884. lasttime = d;
  885. break;
  886. case(0):
  887. if(d > 1 || d < 0) {
  888. fprintf(stdout,"ERROR: Width data %lf out of range 0-1 in width data file\n",d);
  889. fflush(stdout);
  890. return -1;
  891. }
  892. break;
  893. }
  894. istime = !istime;
  895. *p = (float)d;
  896. p++;
  897. n++;
  898. if(n >= arraysize) {
  899. arraysize += 100;
  900. if((*widdat = (float *)realloc((char *)(*widdat),arraysize * sizeof(float)))==NULL) {
  901. fprintf(stdout,"ERROR: Insufficient memory to expand store of rotation data\n");
  902. fflush(stdout);
  903. return -1;
  904. }
  905. }
  906. }
  907. }
  908. if(n&1) {
  909. fprintf(stdout,"ERROR: Width data not correctly paired\n");
  910. fflush(stdout);
  911. return -1;
  912. }
  913. return n;
  914. }
  915. /**************************STRGETFLOAT **************************
  916. * takes a pointer TO A POINTER to a string. If it succeeds in finding
  917. * a float it returns the float value (*val), and it's new position in the
  918. * string (*str).
  919. */
  920. int strgetfloat(char **str,double *val)
  921. { char *p, *q, *end;
  922. double numero;
  923. int point, valid;
  924. for(;;) {
  925. point = 0;
  926. p = *str;
  927. while(isspace(*p))
  928. p++;
  929. q = p;
  930. if(!isdigit(*p) && *p != '.' && *p!='-')
  931. return(0);
  932. if(*p == '.'|| *p == '-') {
  933. if(*p == '-') {
  934. p++;
  935. } else {
  936. point++;
  937. p++;
  938. }
  939. }
  940. for(;;) {
  941. if(*p == '.') {
  942. if(point)
  943. return(0);
  944. else {
  945. point++;
  946. p++;
  947. continue;
  948. }
  949. }
  950. if(isdigit(*p)) {
  951. p++;
  952. continue;
  953. } else {
  954. if(!isspace(*p) && *p!=ENDOFSTR)
  955. return(0);
  956. else {
  957. end = p;
  958. p = q;
  959. valid = 0;
  960. while(p!=end) {
  961. if(isdigit(*p))
  962. valid++;
  963. p++;
  964. }
  965. if(valid) {
  966. if(sscanf(q,"%lf",&numero)!=1)
  967. return(0);
  968. *val = numero;
  969. *str = end;
  970. return(1);
  971. }
  972. return(0);
  973. }
  974. }
  975. }
  976. }
  977. return(0); /* NOTREACHED */
  978. }
  979. /**************************** READ_VALUE_FROM_BRKTABLE *****************************/
  980. int read_value_from_brktable(float *val,float *brk, int brksize, float thistime,int init)
  981. {
  982. float *endpair, *p;
  983. double hival, loval, hiind, loind, thisval;
  984. static float *brkptr, firstval, finaltime, lastval;
  985. if(!init) {
  986. brkptr = brk;
  987. firstval = *(brkptr+1);
  988. endpair = brkptr + ((brksize-1)*2);
  989. finaltime = *endpair;
  990. lastval = *(endpair+1);
  991. }
  992. p = brkptr;
  993. if(thistime <= *brk) {
  994. *val = firstval;
  995. return 1;
  996. } else if(thistime >= finaltime) {
  997. *val = lastval;
  998. return 1;
  999. }
  1000. if(thistime > *p) {
  1001. while(*p < thistime)
  1002. p += 2;
  1003. } else {
  1004. while((*p = thistime))
  1005. p -= 2;
  1006. p += 2;
  1007. }
  1008. hival = *(p+1);
  1009. hiind = *p;
  1010. loval = *(p-1);
  1011. loind = *(p-2);
  1012. thisval = (thistime - loind)/(hiind - loind);
  1013. thisval *= (float)(hival - loval);
  1014. thisval += loval;
  1015. *val = (float)thisval;
  1016. brkptr = p;
  1017. return 1;
  1018. }
  1019. void usage(int mode)
  1020. {
  1021. switch(mode) {
  1022. case(0):
  1023. fprintf(stdout,
  1024. "ERROR: USAGE: spacedesign mode outfile params\n"
  1025. "\n"
  1026. "MODE stom, mtos, rotate\n"
  1027. "STOM collapses stereo image to mono, gradually\n"
  1028. "MTOS spreads from mono image to stereo\n"
  1029. "ROTATE rotates the source\n"
  1030. "\n"
  1031. "Outputs are various control files for enveloping or mixing the source.\n"
  1032. "\n"
  1033. "This program is usually accessed through an interface on the Sound Loom.\n");
  1034. break;
  1035. case(1):
  1036. fprintf(stdout,
  1037. "ERROR: USAGE: spacedesign stom generic_outfilename starttime endtime endpos\n"
  1038. "\n"
  1039. "STARTTIME time at which convergence to mono begins.\n"
  1040. "ENDTIME time at which convergence to mono end.\n"
  1041. "ENDPOS final position of mono image in stereo field.\n");
  1042. break;
  1043. case(2):
  1044. fprintf(stdout,
  1045. "ERROR: USAGE: spacedesign mtos generic_outfilename starttime endtime startpos\n"
  1046. "\n"
  1047. "STARTTIME time at which divergence to stereo begins.\n"
  1048. "ENDTIME time at which divergence to stereo is complete.\n"
  1049. "ENDPOS initial position of mono image in stereo field.\n");
  1050. break;
  1051. case(3):
  1052. fprintf(stdout,
  1053. "ERROR: USAGE: spacedesign rotate generic_outfilename starttime endtime startpos endpos\n"
  1054. "edgetimes width clokwise(0/1) linger loudnessdepth loudnesslead attenuation isfilt warp\n"
  1055. "\n"
  1056. "STARTTIME time at which rotation begins.\n"
  1057. "ENDTIME time at which rotation ends.\n"
  1058. "STARTPOS position of mono image in stereo field when rotation starts.\n"
  1059. "ENDPOS position of mono image in stereo field when rotation ends.\n"
  1060. "EDGETIMES file of (increasing) times at which rotation is at (alternate) edges of space.\n"
  1061. "WIDTH width of rotating circle (0-1) (try 0.9).\n"
  1062. "CLOKWISE rotate clockwise(1) or anticlockwise(0).\n"
  1063. "LINGER linger at edges of space (0-1) (try 0.15).\n"
  1064. "LOUDNESSDEPTH difference in level between front and rear of circle (>=1) (1 = no difference).\n"
  1065. "LOUDNESSLEAD loudest moment precedes central point of rotation by (secs).\n"
  1066. "ATTENUATION overall attenuation.\n"
  1067. "ISFILT (0 or 1) create a file to control balance of src and a filtered version of it?\n"
  1068. "WARP (1-20) greater warp increases proportion of time \"behind\" plane of loudspeakers.\n"); /*RWD was 'plain' */
  1069. break;
  1070. }
  1071. fflush(stdout);
  1072. }
  1073. /**************************** FLTEQ *******************************/
  1074. int flteq(double f1,double f2)
  1075. {
  1076. double upperbnd, lowerbnd;
  1077. upperbnd = f2 + FLTERR;
  1078. lowerbnd = f2 - FLTERR;
  1079. if((f1>upperbnd) || (f1<lowerbnd))
  1080. return(0);
  1081. return(1);
  1082. }
  1083. int isnumeric(char *str)
  1084. {
  1085. char *p = str;
  1086. int pntcnt = 0;
  1087. int valcnt = 0;
  1088. int cnt = 0;
  1089. while(*p != ENDOFSTR) {
  1090. cnt++;
  1091. if(isdigit(*p)) {
  1092. valcnt++;
  1093. p++;
  1094. continue;
  1095. }
  1096. if(*p == '.') {
  1097. pntcnt++;
  1098. if(pntcnt > 1)
  1099. return 0;
  1100. p++;
  1101. continue;
  1102. }
  1103. if(*p == '-') {
  1104. if(cnt != 1)
  1105. return 0;
  1106. p++;
  1107. continue;
  1108. }
  1109. return 0;
  1110. }
  1111. if(valcnt <= 0)
  1112. return 0;
  1113. return 1;
  1114. }