pagrab.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. /*
  2. * Copyright (c) 1983-2023 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. *
  23. * Convert snd data to text format suitable for Pview in Sound Loom
  24. */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <osbind.h>
  29. #include <math.h>
  30. #include <float.h>
  31. #include <float.h>
  32. #include <sfsys.h>
  33. #include <cdplib.h>
  34. #define VIEW_WIDTH 900 /* width of sloom display */
  35. #define VIEW_HEIGHT 300 /* heigth of sloom display */
  36. #define HALF_VIEW_HEIGHT 150 /* half heigth of sloom display */
  37. #define COLOR_SPECTRUM 45 /* number of individual colours supported */
  38. #define EFFECTIVE_VIEW_WIDTH (VIEW_WIDTH - (VIEW_HEIGHT * 2))
  39. #define F_SECSIZE (256)
  40. /* Functions */
  41. static int tidy_up(int,unsigned int);
  42. static int open_in(char*), open_out(char *);
  43. static int get_big_buf(void);
  44. static int write_output(int obufcnt);
  45. static int write_window(int totchans,float *rbuf,int bufcnt);
  46. static int make_outfile(int del,char *filename);
  47. float *bigbuf, *sampbuf, *osambuf;
  48. float arate, frametime;
  49. int buflen, obuflen; /* buffer length in samps */
  50. int ifd, ofd; /* input soundfile descriptor */
  51. int channels; /* number of channels of input */
  52. int startwin, endwin, startchan, endchan, outfilesize, obufcnt;
  53. char outfilename[200];
  54. int srate, origstype, origrate, stype;
  55. int Mlen, Dfac, del;
  56. SFPROPS sfprops = {0};
  57. const char* cdp_version = "7.1.0";
  58. int main(int argc,char *argv[])
  59. {
  60. unsigned int start = hz1000();
  61. double starttime, endtime;
  62. /* initialise SFSYS */
  63. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  64. fprintf(stdout,"%s\n",cdp_version);
  65. fflush(stdout);
  66. return 0;
  67. }
  68. if( sflinit("paview") < 0 ) {
  69. fprintf(stdout,"ERROR: Cannot initialise soundfile system.\n");
  70. fflush(stdout);
  71. return tidy_up(3,start);
  72. }
  73. if(argc!=8) {
  74. fprintf(stdout,"ERROR: Wrong number of arguments.\n");
  75. fflush(stdout);
  76. return tidy_up(2,start);
  77. }
  78. if(sscanf(argv[2],"%lf",&starttime)!=1) {
  79. fprintf(stdout,"ERROR: cannot read start time.\n");
  80. fflush(stdout);
  81. return tidy_up(2,start);
  82. }
  83. if(sscanf(argv[3],"%lf",&endtime)!=1) {
  84. fprintf(stdout,"ERROR: cannot read end time.\n");
  85. fflush(stdout);
  86. return tidy_up(2,start);
  87. }
  88. if(sscanf(argv[4],"%s",outfilename)!=1) {
  89. fprintf(stdout,"ERROR: cannot outfilename.\n");
  90. fflush(stdout);
  91. return tidy_up(2,start);
  92. }
  93. if(sscanf(argv[5],"%d",&startchan)!=1) {
  94. fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
  95. fflush(stdout);
  96. return tidy_up(2,start);
  97. }
  98. if(sscanf(argv[6],"%d",&endchan)!=1) {
  99. fprintf(stdout,"ERROR: cannot read sonogram flag.\n");
  100. fflush(stdout);
  101. return tidy_up(2,start);
  102. }
  103. if(sscanf(argv[7],"%d",&del)!=1) {
  104. fprintf(stdout,"ERROR: cannot read deletion flag.\n");
  105. fflush(stdout);
  106. return tidy_up(2,start);
  107. }
  108. /* open input file */
  109. if(open_in(argv[1]) < 0)
  110. return tidy_up(2,start);
  111. startwin = (int)floor(starttime/frametime);
  112. endwin = (int)ceil(endtime/frametime);
  113. if(open_out(argv[4]) < 0)
  114. return tidy_up(2,start);
  115. /* get biggest buffer */
  116. if(get_big_buf() == 0)
  117. return tidy_up(1,start);
  118. if(make_outfile(del,outfilename)<0)
  119. return tidy_up(1,start);
  120. /* tidy up */
  121. return tidy_up(0,start);
  122. }
  123. /**************************** OPEN_IN ****************************
  124. *
  125. * opens input soundfile and gets header
  126. */
  127. int open_in(char *name) /* opens input soundfile and gets header */
  128. {
  129. if( (ifd = sndopenEx(name,0,CDP_OPEN_RDONLY)) < 0 ) {
  130. fprintf(stdout,"ERROR: Cannot open file: %s\n\t",name);
  131. fflush(stdout);
  132. return(-1);
  133. }
  134. if(snd_headread(ifd,&sfprops)<=0) {
  135. fprintf(stdout,"ERROR: Cannot read file properties: %s\n\t",name);
  136. fflush(stdout);
  137. return(-1);
  138. }
  139. channels = sfprops.chans;
  140. arate = sfprops.arate;
  141. origrate = sfprops.origrate;
  142. Mlen = sfprops.winlen;
  143. Dfac = sfprops.decfac;
  144. frametime = (float)(1.0/ sfprops.arate);
  145. if(sfprops.type != wt_analysis){
  146. fprintf(stdout,"ERROR: %s is not an analysis file\n",name);
  147. fflush(stdout);
  148. return(-1);
  149. }
  150. return 0;
  151. }
  152. /**************************** OPEN_OUT ****************************
  153. *
  154. * opens input soundfile and gets header
  155. */
  156. int open_out(char *name) /* opens input soundfile and gets header */
  157. {
  158. outfilesize = (endwin - startwin) * channels;
  159. if((ofd = sndcreat_ex(name,outfilesize,&sfprops,0,CDP_CREATE_NORMAL)) < 0) {
  160. fprintf(stdout,"ERROR: Cannot open output file %s\n",name);
  161. fflush(stdout);
  162. return(-1);
  163. }
  164. return 0;
  165. }
  166. /**************************** GET_BIG_BUF ****************************
  167. *
  168. * allocates memory for the biggest possible buffer
  169. */
  170. int get_big_buf(void)
  171. {
  172. size_t i;
  173. if((bigbuf=(float*)Malloc(((channels * 4) + F_SECSIZE) * sizeof(float))) == NULL) {
  174. fprintf(stdout,"ERROR: Failed to allocate float buffer.\n");
  175. fflush(stdout);
  176. return 0;
  177. }
  178. i = ((size_t)bigbuf+sizeof(float)-1)/sizeof(float)*sizeof(float); /* align bigbuf to word boundary */
  179. bigbuf = (float*)i;
  180. memset((char *)bigbuf,0,(channels * 4) * sizeof(float));
  181. sampbuf = bigbuf + channels;
  182. /* allow for wrap-around */
  183. buflen = channels;
  184. obuflen = (int)ceil((double)channels / (double)F_SECSIZE);
  185. obuflen *= F_SECSIZE;
  186. osambuf = sampbuf + channels;
  187. /* allow for wrap-around */
  188. return 1;
  189. }
  190. /**************************** MAKE TEXTFILE *****************************/
  191. int make_outfile(int idel,char *filename)
  192. {
  193. int samplen, total_windowsgot_got, samps_remain;
  194. int got, sampsgot, windowsgot, bufcnt;
  195. int channelstoshow, done_display /*, changrpcnt*/;
  196. float *rbuf;
  197. // double channelmax;
  198. int n, displayed_channel_cnt, channel_cnt, totchans;
  199. if((samplen = sndsizeEx(ifd))<0) { /* FIND SIZE OF FILE */
  200. fprintf(stdout, "ERROR: Can't read size of input file %s.\n",filename);
  201. fflush(stdout);
  202. return -1;
  203. }
  204. total_windowsgot_got = 0;
  205. samps_remain = 0;
  206. rbuf = sampbuf;
  207. totchans = channels/2;
  208. if((channelstoshow = endchan - startchan) == 0) {
  209. if(endchan != totchans)
  210. endchan++;
  211. else if(startchan !=0)
  212. startchan--;
  213. channelstoshow++;
  214. }
  215. memset((char *)osambuf,0, obuflen * sizeof(float));
  216. done_display = 0;
  217. obufcnt = 0; /* count in buffer of output values */
  218. while((got = fgetfbufEx(sampbuf,buflen,ifd,1)) > 0 ) {
  219. sampsgot = samps_remain; /* Take into account any wrapped around values */
  220. sampsgot += got;
  221. windowsgot = sampsgot/channels;
  222. samps_remain = sampsgot - (windowsgot * channels);
  223. bufcnt = 0; /* cnt in buffer we're reading from (which includes wrap-around) */
  224. for(n=0;n<windowsgot;n++) { /* for every window */
  225. total_windowsgot_got++; /* count the windows */
  226. if(total_windowsgot_got <= startwin) { /* if not at 1st window to display, continue */
  227. if(idel)
  228. if(write_window(totchans,rbuf,bufcnt)<0)
  229. return -1;
  230. bufcnt += channels;
  231. continue;
  232. }
  233. else if(total_windowsgot_got > endwin) { /* if beyond last window to display, quit */
  234. if(idel) {
  235. if(write_window(totchans,rbuf,bufcnt)<0)
  236. return -1;
  237. bufcnt += channels;
  238. continue;
  239. } else {
  240. done_display = 1;
  241. break;
  242. }
  243. }
  244. // changrpcnt = 0; /* count of set-of-channels to group together for display */
  245. // channelmax = 0.0;
  246. for(channel_cnt=0;channel_cnt < startchan;channel_cnt++) {
  247. if(idel) {
  248. osambuf[obufcnt++] = rbuf[bufcnt++];
  249. osambuf[obufcnt++] = rbuf[bufcnt++];
  250. if(obufcnt >= obuflen) {
  251. if(write_output(obufcnt) < 0)
  252. return -1;
  253. }
  254. } else {
  255. osambuf[obufcnt++] = 0.0;
  256. bufcnt++;
  257. osambuf[obufcnt++] = rbuf[bufcnt++];
  258. if(obufcnt >= obuflen) {
  259. if(write_output(obufcnt) < 0)
  260. return -1;
  261. }
  262. }
  263. }
  264. for(displayed_channel_cnt = 0; displayed_channel_cnt < channelstoshow; displayed_channel_cnt++) {
  265. if(idel) {
  266. osambuf[obufcnt++] = 0.0;
  267. bufcnt++;
  268. osambuf[obufcnt++] = rbuf[bufcnt++];
  269. if(obufcnt >= obuflen) {
  270. if(write_output(obufcnt) < 0)
  271. return -1;
  272. }
  273. } else {
  274. osambuf[obufcnt++] = rbuf[bufcnt++];
  275. osambuf[obufcnt++] = rbuf[bufcnt++];
  276. if(obufcnt >= obuflen) {
  277. if(write_output(obufcnt) < 0)
  278. return -1;
  279. }
  280. }
  281. }
  282. channel_cnt += displayed_channel_cnt;
  283. while(channel_cnt < totchans) {
  284. if(idel) {
  285. osambuf[obufcnt++] = rbuf[bufcnt++];
  286. osambuf[obufcnt++] = rbuf[bufcnt++];
  287. if(obufcnt >= obuflen) {
  288. if(write_output(obufcnt) < 0)
  289. return -1;
  290. }
  291. } else {
  292. osambuf[obufcnt++] = 0.0;
  293. bufcnt++;
  294. osambuf[obufcnt++] = rbuf[bufcnt++];
  295. if(obufcnt >= obuflen) {
  296. if(write_output(obufcnt) < 0)
  297. return -1;
  298. }
  299. }
  300. channel_cnt++;
  301. }
  302. }
  303. if(done_display) /* if reached end of windows to display, quit */
  304. break;
  305. if(samps_remain) { /* if there are extra samples beyond end of windows */
  306. rbuf = sampbuf - samps_remain; /* wrap them around */
  307. memcpy((char *)rbuf,(char *)(rbuf + (windowsgot * channels)),samps_remain * sizeof(float));
  308. } else
  309. rbuf = sampbuf;
  310. }
  311. if(obufcnt >= 0) {
  312. if(write_output(obufcnt) < 0)
  313. return -1;
  314. }
  315. sndcloseEx(ofd);
  316. return(0);
  317. }
  318. /**************************** TIDY_UP ****************************
  319. *
  320. * Exit, freeing buffers and closing files where necessary.
  321. */
  322. int tidy_up(int where,unsigned int start)
  323. {
  324. switch(where) {
  325. case 0:
  326. Mfree(bigbuf);
  327. case 1:
  328. sndcloseEx(ifd);
  329. case 2:
  330. // sffinish();
  331. default:
  332. break;
  333. }
  334. while(!(hz1000() - start))
  335. ;
  336. return(1);
  337. }
  338. /**************************** WRITE_OUTPUT ****************************/
  339. int write_output(int samps_written)
  340. {
  341. if(fputfbufEx(osambuf,samps_written,ofd) < 0) {
  342. fprintf(stdout, "ERROR: Failed to complete data write to analysis output file.\n");
  343. if(sndunlink(ofd) < 0)
  344. fprintf(stdout, "ERROR: Can't set output analysis for deletion.\n");
  345. if(sndcloseEx(ofd) < 0)
  346. fprintf(stdout, "WARNING: Can't close output analysis.\n");
  347. fflush(stdout);
  348. return -1;
  349. }
  350. memset((char *)osambuf,0, obuflen * sizeof(float));
  351. obufcnt = 0;
  352. return 0;
  353. }
  354. /**************************** WRITE_WINDOW ****************************/
  355. int write_window(int totchans,float *rbuf,int bufcnt)
  356. {
  357. int channel_cnt;
  358. for(channel_cnt=0;channel_cnt < totchans;channel_cnt++) {
  359. osambuf[obufcnt++] = rbuf[bufcnt++];
  360. osambuf[obufcnt++] = rbuf[bufcnt++];
  361. if(obufcnt >= obuflen) {
  362. if(write_output(obufcnt) < 0)
  363. return -1;
  364. }
  365. }
  366. return 0;
  367. }