simple.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  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. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <structures.h>
  24. #include <tkglobals.h>
  25. #include <pnames.h>
  26. #include <globcon.h>
  27. #include <processno.h>
  28. #include <modeno.h>
  29. #include <arrays.h>
  30. #include <simple.h>
  31. #include <cdpmain.h>
  32. #include <formants.h>
  33. #include <speccon.h>
  34. #include <sfsys.h>
  35. #include <string.h>
  36. #include <simple.h>
  37. #define VERYBIG (10000.0)
  38. #define SRCFILE (0)
  39. #define NOISEFILE (1)
  40. #define COMPAREFILE (2)
  41. //#ifdef unix
  42. #define round(x) lround((x))
  43. //#endif
  44. static int copy_cut_samps(int startwindow,int *endwindow,int windows_per_buf,int endchunksize,dataptr dz);
  45. static int outer_clean_loop(int whichfile,int no_of_marked_channels,dataptr dz);
  46. static int adjust_noise_level(dataptr dz);
  47. static int setup_cleaning_filter(dataptr dz);
  48. static int reorganise_marks(int *no_of_marked_channels,dataptr dz);
  49. static int read_noise_data(int windows_in_buffer,dataptr dz);
  50. static int read_comparison_data(int windows_in_buffer,dataptr dz);
  51. static int do_cleaning(int windows_in_buffer,int no_of_marked_channels,dataptr dz);
  52. static int skip_skipwindows(int *wc,int windows_in_buffer,dataptr dz);
  53. static int generate_magnified_outfile(dataptr dz);
  54. static int read_cut_samps(dataptr dz);
  55. /*********************** SPECGAIN ***************************/
  56. int specgain(dataptr dz)
  57. {
  58. int vc;
  59. for( vc = 0; vc < dz->wanted; vc += 2)
  60. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[GAIN_GAIN]);
  61. return(FINISHED);
  62. }
  63. /*********************** SPECLIMIT ***************************/
  64. int speclimit(dataptr dz)
  65. {
  66. int vc;
  67. for( vc = 0; vc < dz->wanted; vc += 2) {
  68. if(dz->flbufptr[0][AMPP] < dz->param[LIMIT_THRESH])
  69. dz->flbufptr[0][AMPP] = 0.0f;
  70. }
  71. return(FINISHED);
  72. }
  73. /**************************** SPECCLEAN ***************************/
  74. int specclean(dataptr dz)
  75. {
  76. int exit_status;
  77. int no_of_marked_channels = 0;
  78. if((exit_status = outer_clean_loop(NOISEFILE,no_of_marked_channels,dz))<0)
  79. return(exit_status);
  80. if((exit_status = adjust_noise_level(dz))<0)
  81. return(exit_status);
  82. switch(dz->mode) {
  83. case(FILTERING):
  84. if((exit_status = setup_cleaning_filter(dz))<0)
  85. return(exit_status);
  86. break;
  87. case(COMPARING):
  88. if((exit_status = outer_clean_loop(COMPAREFILE,no_of_marked_channels,dz))<0)
  89. return(exit_status);
  90. if((exit_status = reorganise_marks(&no_of_marked_channels,dz))<0)
  91. return(exit_status);
  92. break;
  93. }
  94. return outer_clean_loop(SRCFILE,no_of_marked_channels,dz);
  95. }
  96. /**************************** OUTER_CLEAN_LOOP ****************************/
  97. int outer_clean_loop(int whichfile,int no_of_marked_channels,dataptr dz)
  98. {
  99. int exit_status;
  100. int samps_read, windows_in_buffer;
  101. while((samps_read = fgetfbufEx(dz->bigfbuf, dz->big_fsize,dz->ifd[whichfile],0)) > 0) {
  102. dz->flbufptr[0] = dz->bigfbuf;
  103. windows_in_buffer = samps_read/dz->wanted;
  104. switch(whichfile) {
  105. case(NOISEFILE):
  106. if((exit_status = read_noise_data(windows_in_buffer,dz))<0)
  107. return(exit_status);
  108. break;
  109. case(COMPAREFILE):
  110. if((exit_status = read_comparison_data(windows_in_buffer,dz))<0)
  111. return(exit_status);
  112. break;
  113. case(SRCFILE):
  114. if((exit_status = do_cleaning(windows_in_buffer,no_of_marked_channels,dz))<0)
  115. return(exit_status);
  116. break;
  117. default:
  118. sprintf(errstr,"Unknown option in outer_clean_loop()\n");
  119. return(PROGRAM_ERROR);
  120. }
  121. if(whichfile==SRCFILE && (samps_read > 0)) {
  122. if((exit_status = write_exact_samps(dz->bigfbuf,samps_read,dz))<0)
  123. return(exit_status);
  124. }
  125. }
  126. if(samps_read<0) {
  127. sprintf(errstr,"Sound read error.\n");
  128. return(SYSTEM_ERROR);
  129. }
  130. if(whichfile!=SRCFILE)
  131. dz->time = 0.0f;
  132. return(FINISHED);
  133. }
  134. /************************ ADJUST_NOISE_LEVEL **********************/
  135. int adjust_noise_level(dataptr dz)
  136. {
  137. int cc;
  138. for( cc = 0; cc < dz->clength; cc++)
  139. dz->amp[cc] = (float)(dz->amp[cc] * dz->param[CL_GAIN]);
  140. return(FINISHED);
  141. }
  142. /************************* SETUP_CLEANING_FILTER ***************************/
  143. int setup_cleaning_filter(dataptr dz)
  144. {
  145. int cc, vc;
  146. double chtop = dz->chwidth/2.0;
  147. if(chtop < dz->param[CL_FRQ])
  148. dz->amp[0] = 0.0f;
  149. for( cc = 1, vc = 2; cc < dz->clength; cc++, vc +=2) {
  150. chtop += dz->chwidth;
  151. if(chtop < dz->param[CL_FRQ])
  152. dz->amp[cc] = 0.0f;
  153. }
  154. return(FINISHED);
  155. }
  156. /************************ REORGANISE_MARKS **********************
  157. *
  158. * Instead of keeping 1024 marks, keep the locations of all SET marks!!
  159. * Convert locations fron channel no (cc) to buffer location (vc)
  160. */
  161. int reorganise_marks(int *no_of_marked_channels,dataptr dz)
  162. {
  163. int n;
  164. *no_of_marked_channels = 0;
  165. for(n=0;n < dz->clength;n++) {
  166. if(dz->iparray[CL_MARK][n]) {
  167. dz->iparray[CL_MARK][*no_of_marked_channels] = n;
  168. (*no_of_marked_channels)++;
  169. }
  170. }
  171. if(*no_of_marked_channels==0) {
  172. sprintf(errstr,"Comparison file is already clean, relative to noisefile.\n");
  173. return(GOAL_FAILED);
  174. }
  175. for(n=0;n < *no_of_marked_channels; n++) /* change marks from cc to vc */
  176. dz->iparray[CL_MARK][n] *= 2;
  177. return(FINISHED);
  178. }
  179. /************************* READ_NOISE_DATA ***************************/
  180. int read_noise_data(int windows_in_buffer,dataptr dz)
  181. {
  182. int wc;
  183. int cc, vc;
  184. for(wc=0; wc<windows_in_buffer; wc++) {
  185. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  186. if(dz->flbufptr[0][AMPP] > dz->amp[cc])
  187. dz->amp[cc] = dz->flbufptr[0][AMPP];
  188. }
  189. dz->flbufptr[0] += dz->wanted;
  190. }
  191. return(FINISHED);
  192. }
  193. /************************* READ_COMPARISON_DATA ***************************/
  194. int read_comparison_data(int windows_in_buffer,dataptr dz)
  195. {
  196. int wc;
  197. int cc, vc;
  198. for(wc=0; wc<windows_in_buffer; wc++) {
  199. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  200. if(dz->flbufptr[0][AMPP] > dz->amp[cc])
  201. dz->iparray[CL_MARK][cc] = 0;
  202. }
  203. dz->flbufptr[0] += dz->wanted;
  204. }
  205. return(FINISHED);
  206. }
  207. /************************* DO_CLEANING ***************************/
  208. int do_cleaning(int windows_in_buffer,int no_of_marked_channels,dataptr dz)
  209. {
  210. int exit_status;
  211. int wc = 0;
  212. int n, cc, vc;
  213. switch(dz->mode) {
  214. case(COMPARING):
  215. for(wc=0; wc<windows_in_buffer; wc++) {
  216. for(n=0;n<no_of_marked_channels;n++)
  217. dz->flbufptr[0][dz->iparray[CL_MARK][n]] = 0.0F;
  218. dz->flbufptr[0] += dz->wanted;
  219. }
  220. break;
  221. case(FROMTIME):
  222. case(ANYWHERE):
  223. wc = 0;
  224. if(!dz->finished) {
  225. if((exit_status = skip_skipwindows(&wc,windows_in_buffer,dz))<0)
  226. return(exit_status);
  227. if(exit_status==FINISHED)
  228. break;
  229. }
  230. /* fall thro */
  231. case(FILTERING):
  232. for(; wc<windows_in_buffer; wc++) {
  233. for(cc=0, vc = 0;cc < dz->clength; cc++, vc += 2) {
  234. if(dz->flbufptr[0][AMPP] < dz->amp[cc]) {
  235. dz->flbufptr[0][AMPP] = 0.0F;
  236. if(dz->mode==FROMTIME)
  237. dz->amp[cc] = (float)VERYBIG;
  238. }
  239. }
  240. dz->flbufptr[0] += dz->wanted;
  241. }
  242. break;
  243. default:
  244. sprintf(errstr,"unknown case in do_cleaning()\n");
  245. return(PROGRAM_ERROR);
  246. }
  247. return(FINISHED);
  248. }
  249. /************************ SKIP_SKIPWINDOWS **********************/
  250. int skip_skipwindows(int *wc,int windows_in_buffer,dataptr dz)
  251. {
  252. int step;
  253. if((step = dz->iparam[CL_SKIPW] - dz->total_windows) >= windows_in_buffer) {
  254. dz->total_windows += windows_in_buffer;
  255. dz->time += dz->frametime * windows_in_buffer;
  256. return(FINISHED);
  257. } else {
  258. dz->total_windows += step;
  259. *wc = step;
  260. dz->time += dz->frametime * step;
  261. dz->flbufptr[0] += step * dz->wanted;
  262. dz->finished = TRUE;
  263. }
  264. return(CONTINUE);
  265. }
  266. /************************* SPECCUT ***************************/
  267. int speccut(dataptr dz)
  268. {
  269. int exit_status;
  270. int samps_remain, bufs_to_skip, endchunksize;
  271. int startwindow = (int)(dz->param[CUT_STIME]/dz->frametime);
  272. int endwindow = (int)(dz->param[CUT_ETIME]/dz->frametime);
  273. int windows_per_buf = dz->big_fsize/dz->wanted;
  274. int w_to_skip = 0;
  275. endwindow = min(endwindow,dz->wlength);
  276. if((bufs_to_skip = startwindow/windows_per_buf) > 0) { /* TRUNCATE */
  277. w_to_skip = bufs_to_skip * windows_per_buf;
  278. if((sndseekEx(dz->ifd[0],w_to_skip * dz->wanted,0))<0) {
  279. sprintf(errstr,"Window seek failed: speccut().\n");
  280. return(SYSTEM_ERROR);
  281. }
  282. }
  283. startwindow -= w_to_skip;
  284. endwindow -= w_to_skip;
  285. if((exit_status = read_cut_samps(dz))<0)
  286. return(exit_status);
  287. dz->flbufptr[0] = dz->bigfbuf + (startwindow * dz->wanted);
  288. endchunksize = windows_per_buf - startwindow;
  289. dz->flbufptr[1] = dz->flbufptr[2];
  290. if(endwindow > 0) {
  291. do {
  292. if((exit_status = copy_cut_samps(startwindow,&endwindow,windows_per_buf,endchunksize,dz))<0)
  293. return(exit_status);
  294. } while(exit_status==CONTINUE);
  295. }
  296. if((samps_remain = dz->flbufptr[1] - dz->flbufptr[2]) > 0) {
  297. if((exit_status = write_samps(dz->flbufptr[2],samps_remain,dz))<0)
  298. return(exit_status);
  299. }
  300. return(FINISHED);
  301. }
  302. /************************* COPY_CUT_SAMPS ***************************/
  303. int copy_cut_samps(int startwindow,int *endwindow,int windows_per_buf,int endchunksize,dataptr dz)
  304. {
  305. int exit_status;
  306. if(*endwindow >= windows_per_buf) {
  307. memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)(endchunksize * dz->wanted * sizeof(float)));
  308. dz->flbufptr[1] += endchunksize * dz->wanted;
  309. dz->flbufptr[0] = dz->bigfbuf;
  310. if((exit_status = read_cut_samps(dz))<0)
  311. return(exit_status);
  312. *endwindow -= windows_per_buf;
  313. } else {
  314. memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)((*endwindow - startwindow) * dz->wanted * sizeof(float)));
  315. dz->flbufptr[1] += (*endwindow - startwindow) * dz->wanted;
  316. return(FINISHED);
  317. }
  318. if(*endwindow >= startwindow) {
  319. if(startwindow > 0)
  320. memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)(startwindow * dz->wanted * sizeof(float)));
  321. if((exit_status = write_exact_samps(dz->flbufptr[2],dz->big_fsize,dz))<0)
  322. return(exit_status);
  323. dz->flbufptr[1] = dz->flbufptr[2];
  324. dz->flbufptr[0] += startwindow * dz->wanted;
  325. } else {
  326. memmove((char *)dz->flbufptr[1],(char *)dz->flbufptr[0],(size_t)(*endwindow * dz->wanted * sizeof(float)));
  327. dz->flbufptr[1] += *endwindow * dz->wanted;
  328. return(FINISHED);
  329. }
  330. return(CONTINUE);
  331. }
  332. /****************************** SPECGRAB_OR_MAGNIFY ***************************/
  333. int specgrab_or_magnify(int frztime_paramno,dataptr dz)
  334. {
  335. int exit_status;
  336. int frzwindow, bufs_to_seek, samps_read;
  337. int big_wsize = dz->big_fsize/dz->wanted;
  338. frzwindow = (int)(dz->param[frztime_paramno]/dz->frametime); /* truncate */
  339. frzwindow = min(frzwindow,dz->wlength-1); /* if time > filelen, get last window */
  340. bufs_to_seek = (frzwindow * dz->wanted)/dz->big_fsize; /* truncate */
  341. if(sndseekEx(dz->ifd[0],bufs_to_seek * dz->big_fsize,0)<0) {
  342. sprintf(errstr,"seek failed in specgrab_or_magnify().\n");
  343. return(SYSTEM_ERROR);
  344. }
  345. if((samps_read = fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0)) < dz->wanted) {
  346. if(samps_read<0) {
  347. sprintf(errstr,"Sound read error.\n");
  348. return(SYSTEM_ERROR);
  349. } else {
  350. sprintf(errstr,"Problem reading infile data in specgrab_or_magnify().\n");
  351. return(PROGRAM_ERROR);
  352. }
  353. }
  354. frzwindow -= bufs_to_seek * big_wsize;
  355. dz->flbufptr[0] = dz->bigfbuf + (frzwindow * dz->wanted);
  356. switch(dz->process) {
  357. case(GRAB):
  358. if((exit_status = write_samps(dz->flbufptr[0],dz->wanted,dz))<0)
  359. return(exit_status);
  360. break;
  361. case(MAGNIFY):
  362. dz->total_windows = round(dz->param[MAG_DUR]/dz->frametime);
  363. return generate_magnified_outfile(dz);
  364. break;
  365. default:
  366. sprintf(errstr,"unknown application in specgrab_or_magnify()\n");
  367. return(PROGRAM_ERROR);
  368. }
  369. return(FINISHED);
  370. }
  371. /******************************** GENERATE_MAGNIFIED_OUTFILE **********************************/
  372. int generate_magnified_outfile(dataptr dz)
  373. {
  374. int exit_status;
  375. int wc, windows_left;
  376. int vc, cc, written_whole_buffer = 0;
  377. int w_to_buf = dz->big_fsize/dz->wanted;
  378. float *bigbufend = dz->bigfbuf + dz->big_fsize;
  379. memmove((char *)dz->windowbuf[0],(char *)dz->flbufptr[0],(size_t)(dz->wanted * sizeof(float)));
  380. dz->flbufptr[0] = dz->bigfbuf;
  381. for(wc=0; wc<dz->total_windows; wc++) {
  382. memmove((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],(size_t)(dz->wanted * sizeof(float)));
  383. if((dz->flbufptr[0] += dz->wanted) >= bigbufend) {
  384. if(!written_whole_buffer) {
  385. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2)
  386. dz->bigfbuf[vc] = 0.0F; /* ZERO AMPS IN WINDOW ONE */
  387. }
  388. if((exit_status = write_exact_samps(dz->bigfbuf,dz->big_fsize,dz))<0)
  389. return(exit_status);
  390. if(!written_whole_buffer) /* RESTORE DATA IN WINDOW ONE */
  391. memmove((char *)dz->bigfbuf,(char *)dz->windowbuf[0],(size_t)(dz->wanted * sizeof(float)));
  392. written_whole_buffer = 1;
  393. dz->flbufptr[0] = dz->bigfbuf;
  394. }
  395. }
  396. if(!written_whole_buffer) {
  397. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2)
  398. dz->bigfbuf[vc] = 0.0F; /* ZERO AMPS IN WINDOW ONE */
  399. if(dz->flbufptr[0] - dz->bigfbuf > 0) {
  400. if((exit_status = write_samps(dz->bigfbuf,dz->flbufptr[0] - dz->bigfbuf,dz))<0)
  401. return(exit_status);
  402. }
  403. } else {
  404. if((windows_left = dz->total_windows % w_to_buf)> 0) {
  405. if((exit_status = write_samps(dz->bigfbuf,windows_left * dz->wanted,dz))<0)
  406. return(exit_status);
  407. }
  408. }
  409. return(FINISHED);
  410. }
  411. /************************* READ_CUT_SAMPS ***************************/
  412. int read_cut_samps(dataptr dz)
  413. {
  414. if(fgetfbufEx(dz->bigfbuf,dz->big_fsize,dz->ifd[0],0) < 0) {
  415. sprintf(errstr,"Window read failed: read_cut_samps().\n");
  416. return(SYSTEM_ERROR);
  417. }
  418. return(FINISHED);
  419. }