graprepro.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  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. /* floatsam version */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <structures.h>
  25. #include <tkglobals.h>
  26. #include <cdpmain.h>
  27. #include <globcon.h>
  28. #include <processno.h>
  29. #include <grain.h>
  30. #include <arrays.h>
  31. #include <sfsys.h>
  32. //#ifdef unix
  33. #define round(x) lround((x))
  34. //#endif
  35. static int get_grain_envelope(dataptr dz);
  36. static int convert_arraytimelist_to_abs_samplecnts(double *thisarray,int thissize,dataptr dz);
  37. static int convert_gate_time_to_abs_samplecnts(int paramno,dataptr dz);
  38. static int insert_limit_vals(int gate_paramno,dataptr dz);
  39. static void do_arbitrary_param_presets(dataptr dz);
  40. static void convert_sampletime_to_samplegap(dataptr dz);
  41. static int make_grain_splicetable(dataptr dz);
  42. static void offset_synctimes(dataptr dz);
  43. static int readenv(int samps_to_process,int winsamps,float *maxsamp,double **winptr,dataptr dz);
  44. static double getmaxsamp(int startsamp,float *maxsamp, int winsamps,dataptr dz);
  45. static int normalise_env(dataptr dz);
  46. static int seek_to_start_and_zero_all_counters(dataptr dz);
  47. static void create_envsteps(dataptr dz);
  48. /**************************** GRAIN_PREPROCESS ******************************/
  49. int grain_preprocess(int gate_paramno,dataptr dz)
  50. {
  51. int exit_status;
  52. int chans = dz->infile->channels;
  53. /* setup params for reading gate-vals */
  54. int splice_samplen;
  55. dz->ptr[GR_GATEVALS] = NULL;
  56. dz->itemcnt = 0;
  57. if(dz->iparam[GR_WSIZE_SAMPS]>0) {
  58. fprintf(stdout,"INFO: Extracting amplitude envelope of source.\n");
  59. fflush(stdout);
  60. if((exit_status = get_grain_envelope(dz))<0)
  61. return(exit_status);
  62. fprintf(stdout,"INFO: Processing grains.\n");
  63. fflush(stdout);
  64. }
  65. if(dz->brksize[gate_paramno]) {
  66. if((exit_status = convert_gate_time_to_abs_samplecnts(gate_paramno,dz))<0)
  67. return(exit_status);
  68. if((exit_status = insert_limit_vals(gate_paramno,dz))<0) /* CARE - ONLY WORKS FOR FILE0 */
  69. return(exit_status);
  70. dz->brkptr[gate_paramno] = dz->brk[gate_paramno];
  71. dz->ptr[GR_GATEVALS] = dz->brk[gate_paramno];
  72. dz->iparam[GR_THISBRKSAMP] = round(*(dz->ptr[GR_GATEVALS]++));
  73. dz->param[GR_GATE] = *(dz->ptr[GR_GATEVALS]++);
  74. dz->iparam[GR_NEXTBRKSAMP] = round(*(dz->ptr[GR_GATEVALS]++));
  75. dz->param[GR_NEXTGATE] = *(dz->ptr[GR_GATEVALS]++);
  76. dz->param[GR_GATESTEP] = (dz->param[GR_NEXTGATE] - dz->param[GR_GATE])
  77. /(double)(dz->iparam[GR_NEXTBRKSAMP]-dz->iparam[GR_THISBRKSAMP]);
  78. if(dz->param[GR_GATESTEP]>0.0)
  79. dz->iparam[GR_UP] = TRUE;
  80. else
  81. dz->iparam[GR_UP] = FALSE;
  82. if((dz->iparam[GR_TESTLIM] = dz->iparam[GR_NEXTBRKSAMP] - 1000)<dz->iparam[GR_THISBRKSAMP])
  83. dz->iparam[GR_TESTLIM] = dz->iparam[GR_NEXTBRKSAMP];
  84. dz->ptr[GR_GATEBRKEND] = dz->brk[gate_paramno] + (dz->brksize[gate_paramno] * 2);
  85. dz->brksize[gate_paramno] = 0; /* Comment: prevents programs RE-READING brktable (using TIME as index)
  86. where it calls "read_values_from_all_existing_brktables()" */
  87. } else
  88. do_arbitrary_param_presets(dz); /* otherwise program thinks param not assigned, and objects */
  89. dz->param[GR_NGATE] = -dz->param[GR_GATE];
  90. /* setup splicing params */
  91. dz->iparam[GR_SPLICELEN] = round(GRAIN_SPLICELEN * MS_TO_SECS * (double)dz->infile->srate);
  92. if(ODD(dz->iparam[GR_SPLICELEN]))
  93. dz->iparam[GR_SPLICELEN]++; /* Needs to be even as we use HALF of it */
  94. dz->param[GR_SPLUS1] = (double)dz->iparam[GR_SPLICELEN] + 1.0;
  95. dz->iparam[GR_ABS_SPLICELEN] = dz->iparam[GR_SPLICELEN] * chans;
  96. dz->iparam[GR_ABS_SPLICEX2] = dz->iparam[GR_ABS_SPLICELEN] * 2;
  97. dz->iparam[GR_MINHOLE] = (int)(round(dz->param[GR_MINTIME] * (double)dz->infile->srate) * chans);
  98. splice_samplen = (dz->iparam[GR_SPLICELEN]/2) * chans;
  99. if(dz->process!=GRAIN_GET && dz->process!=GRAIN_COUNT && dz->process!=GRAIN_ASSESS) {
  100. if((dz->extrabuf[0] = (float *)malloc(splice_samplen * sizeof(float)))==NULL) {
  101. sprintf(errstr,"INSUFFICIENT MEMORY for splice buffer.\n");
  102. return(MEMORY_ERROR); /* setup 1st splicebuf */
  103. }
  104. if((dz->extrabuf[1] = (float *)malloc(splice_samplen * sizeof(float)))==NULL) {
  105. sprintf(errstr,"INSUFFICIENT MEMORY for 2nd splice buffer.");
  106. return(MEMORY_ERROR); /* setup 2nd splicebuf */
  107. }
  108. if((exit_status = make_grain_splicetable(dz))<0)
  109. return(exit_status);
  110. }
  111. switch(dz->process) {
  112. case(GRAIN_POSITION): /* Check offset value, converting to abs_samplecnt */
  113. dz->param[GR_OFFSET] = (double)(round(dz->param[GR_OFFSET] *(double)dz->infile->srate) * chans);
  114. if((exit_status = convert_arraytimelist_to_abs_samplecnts
  115. (dz->parray[GR_SYNCTIME],(int)dz->iparam[GR_SYNCCNT],dz))<0)
  116. return(exit_status);
  117. if(dz->param[GR_OFFSET] > 0.0)
  118. offset_synctimes(dz); /* Add offset */
  119. convert_sampletime_to_samplegap(dz); /* Convert abs_grain_samptimes to gaps between grains */
  120. if((dz->extrabuf[2] = (float *)malloc(dz->buflen * sizeof(float)))==NULL) {
  121. sprintf(errstr,"INSUFFICIENT MEMORY for sound copying array.\n");
  122. return(MEMORY_ERROR); /* setup buffer for snd copying */
  123. }
  124. break;
  125. case(GRAIN_REVERSE): /* Establish array to store abs_grain_positions */
  126. dz->iparam[GR_ARRAYSIZE] = BIGARRAY;
  127. if((dz->lparray[GR_ABS_POS] = (int *)malloc(dz->iparam[GR_ARRAYSIZE] * sizeof(int)))==NULL) {
  128. sprintf(errstr,"INSUFFICIENT MEMORY for grain times array.\n");
  129. return(MEMORY_ERROR);
  130. }
  131. break;
  132. case(GRAIN_REPITCH):
  133. case(GRAIN_REMOTIF):
  134. dz->iparam[GR_STORESIZE] = NOMINAL_LENGTH;
  135. if((dz->extrabuf[2] = (float *)malloc(dz->iparam[GR_STORESIZE] * sizeof(float)))==NULL) {
  136. sprintf(errstr,"INSUFFICIENT MEMORY for sound copying buffer.\n");
  137. return(MEMORY_ERROR); /* setup buffer for snd copying */
  138. }
  139. }
  140. return(FINISHED);
  141. }
  142. /**************************** OFFSET_SYNCTIMES ***************************/
  143. void offset_synctimes(dataptr dz)
  144. {
  145. int n;
  146. for(n=0;n<dz->iparam[GR_SYNCCNT];n++)
  147. dz->parray[GR_SYNCTIME][n] = (double)round(dz->parray[GR_SYNCTIME][n] + dz->param[GR_OFFSET]);
  148. }
  149. /******************************** GET_GRAIN_ENVELOPE *****************************/
  150. int get_grain_envelope(dataptr dz)
  151. {
  152. int exit_status;
  153. int n, bufcnt;
  154. int winsamps = dz->iparam[GR_WSIZE_SAMPS];
  155. double *winptr;
  156. float maxsamp = 0;
  157. if(((bufcnt = dz->insams[0]/dz->buflen)*dz->buflen)!=dz->insams[0])
  158. bufcnt++; /* Find number of buffers contained in file. */
  159. if(((dz->iparam[GR_WINCNT] =
  160. dz->insams[0]/dz->iparam[GR_WSIZE_SAMPS])
  161. * dz->iparam[GR_WSIZE_SAMPS])!=dz->insams[0])
  162. dz->iparam[GR_WINCNT]++; /* Find number of windows contained in file. */
  163. if((dz->parray[GR_ENVEL]=(double *)malloc(dz->iparam[GR_WINCNT] * sizeof(double)))==NULL) {
  164. sprintf(errstr,"INSUFFICIENT MEMORY for envelope store.\n");
  165. return(MEMORY_ERROR);
  166. }
  167. dz->ptr[GR_ENVEND] = dz->parray[GR_ENVEL] + dz->iparam[GR_WINCNT];
  168. if((dz->parray[GR_ENVSTEP]=(double *)malloc(dz->iparam[GR_WINCNT] * sizeof(double)))==NULL) {
  169. sprintf(errstr,"INSUFFICIENT MEMORY for envelope step store.\n");
  170. return(MEMORY_ERROR);
  171. }
  172. dz->ptr[GR_ESTEPEND] = dz->parray[GR_ENVSTEP] + dz->iparam[GR_WINCNT];
  173. winptr = dz->parray[GR_ENVEL];
  174. if(sloom) {
  175. fprintf(stdout,"INFO: Extracting sound envelope.\n");
  176. fflush(stdout);
  177. }
  178. for(n = 0; n < bufcnt; n++) {
  179. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  180. return(exit_status);
  181. if(sloom)
  182. display_virtual_time(dz->total_samps_read,dz);
  183. if((exit_status = readenv(dz->ssampsread,winsamps,&maxsamp,&winptr,dz))<0)
  184. return(exit_status);
  185. }
  186. if((exit_status = normalise_env(dz))<0)
  187. return(exit_status);
  188. create_envsteps(dz);
  189. if(sloom) {
  190. fprintf(stdout,"INFO: Proceeding to grain extraction.\n");
  191. fflush(stdout);
  192. }
  193. return seek_to_start_and_zero_all_counters(dz);
  194. }
  195. /******************************* CONVERT_ARRAYTIMELIST_TO_ABS_SAMPLECNTS *******************************/
  196. int convert_arraytimelist_to_abs_samplecnts(double *thisarray,int thissize,dataptr dz)
  197. {
  198. double *p, *pend;
  199. if(thisarray==NULL) {
  200. sprintf(errstr,"Array not initialised in convert_arraytimelist_to_abs_samplecnts()\n");
  201. return(PROGRAM_ERROR);
  202. }
  203. if(thissize <= 0) {
  204. sprintf(errstr,"Array size invalid (<=0) in convert_arraytimelist_to_abs_samplecnts()\n");
  205. return(PROGRAM_ERROR);
  206. }
  207. p = thisarray;
  208. pend = thisarray + thissize;
  209. while(p < pend) {
  210. *p = (double)(round(*p * (double)(dz->infile->srate)) * dz->infile->channels);
  211. p++;
  212. }
  213. return(FINISHED);
  214. }
  215. /***************************** CONVERT_GATE_TIME_TO_ABS_SAMPLECNTS *******************************/
  216. int convert_gate_time_to_abs_samplecnts(int paramno,dataptr dz)
  217. {
  218. double *p, *pend;
  219. double lasttime = 0.0;
  220. if(dz->brksize==NULL) {
  221. sprintf(errstr,"brksize not initialised:convert_gate_time_to_abs_samplecnts()\n");
  222. return(PROGRAM_ERROR);
  223. }
  224. if(dz->brksize[paramno]) {
  225. if(dz->brk==NULL) {
  226. sprintf(errstr,"brk not initialised:convert_gate_time_to_abs_samplecnts()\n");
  227. return(PROGRAM_ERROR);
  228. }
  229. p = dz->brk[paramno];
  230. pend = dz->brk[paramno] + (dz->brksize[paramno] * 2);
  231. while(p < pend) {
  232. *p = (double)(round(*p * (double)dz->infile->srate) * dz->infile->channels);
  233. if(p == dz->brk[paramno]) {
  234. if(*p < 0.0) {
  235. sprintf(errstr,"Subzero time encountered in brkpnt file for gate.\n");
  236. return(DATA_ERROR);
  237. }
  238. lasttime = *p;
  239. } else if(*p <= lasttime) {
  240. sprintf(errstr,"Times, when converted to sample-cnts, don't advance in brkfile\n");
  241. return(DATA_ERROR);
  242. }
  243. lasttime = *p;
  244. p += 2;
  245. }
  246. } else
  247. dz->param[paramno] = (double)(round(dz->param[paramno] * (double)dz->infile->srate) * dz->infile->channels);
  248. return(FINISHED);
  249. }
  250. /************************** INSERT_LIMIT_VALS ***************************/
  251. int insert_limit_vals(int gate_paramno,dataptr dz) /* CARE: ASSUMES WE'RE DEALING WITH FILE 0 */
  252. {
  253. double timediff, truediff, ratio, valdiff;
  254. double *q, *p = dz->brk[gate_paramno];
  255. if(*p != 0.0) { /* IF NO VALUE AT ZEROTIME */
  256. dz->brksize[gate_paramno]++;
  257. if((dz->brk[gate_paramno] = (double *)realloc
  258. ((char *)dz->brk[gate_paramno],dz->brksize[gate_paramno] * 2 * sizeof(double)))==NULL) {
  259. sprintf(errstr,"INSUFFICIENT MEMORY for array limit values.\n");
  260. return(MEMORY_ERROR); /* create any extra pair-location */
  261. }
  262. p = dz->brk[gate_paramno] + (dz->brksize[gate_paramno] * 2) - 1;
  263. q = p - 2;
  264. while(q >= dz->brk[gate_paramno]) { /* shuffle values up by 2 places */
  265. *p = *q;
  266. p--;
  267. q--;
  268. }
  269. p = dz->brk[gate_paramno]+1; /* copy post-zerotime value into zero-time value */
  270. q = p + 2;
  271. *p-- = *q;
  272. *p = 0.0; /* insert zero-time at start */
  273. }
  274. p = dz->brk[gate_paramno] + (dz->brksize[gate_paramno] * 2) - 2;
  275. if(*p < dz->insams[0]) { /* IF VALUES DON'T REACH ENDOFFILE-TIME */
  276. dz->brksize[gate_paramno]++;
  277. if((dz->brk[gate_paramno] = (double *)realloc
  278. ((char *)dz->brk[gate_paramno],dz->brksize[gate_paramno] * 2 * sizeof(double)))==NULL) {
  279. sprintf(errstr,"INSUFFICIENT MEMORY for array limit values.\n");
  280. return(MEMORY_ERROR); /* create any extra pair-location */
  281. }
  282. p = dz->brk[gate_paramno] + (dz->brksize[gate_paramno] * 2) - 1;
  283. q = p - 2; /* copy endtime value into endoffile-val location */
  284. *p-- = *q;
  285. *p = dz->insams[0] + 2; /* Put endoffile time in endoffile-time location (+2 for safety) */
  286. } else if (*p > dz->insams[0]) { /* IF VALUES REACH BEYOND ENDOFFILE-TIME */
  287. while(*p > dz->insams[0]) {
  288. p -= 2; /* step back to value AT or before endoffile-time */
  289. dz->brksize[gate_paramno]--; /* adjusting brktable size */
  290. }
  291. if(*p < dz->insams[0]) { /* If value now reached is before endoffile-time */
  292. dz->brksize[gate_paramno]++; /* readjust brktable size upwards */
  293. q = p + 2; /* create an interpolated value for endoffile-time */
  294. timediff = *q - *p;
  295. truediff = dz->insams[0] - *p;
  296. ratio = truediff/timediff;
  297. *q = (double)dz->insams[0];
  298. p++;
  299. q++;
  300. valdiff = *q - *p;
  301. valdiff *= ratio;
  302. *q = *p + valdiff;
  303. } /* and finally, readjust the brktable-space to its true size */
  304. if((dz->brk[gate_paramno] = (double *)realloc
  305. ((char *)dz->brk[gate_paramno],dz->brksize[gate_paramno] * 2 * sizeof(double)))==NULL) {
  306. sprintf(errstr,"INSUFFICIENT MEMORY to reallocate values.\n");
  307. return(MEMORY_ERROR);
  308. }
  309. }
  310. return(FINISHED);
  311. }
  312. /************************** DO_ARBITRARY_PARAM_PRESETS ***************************/
  313. void do_arbitrary_param_presets(dataptr dz)
  314. {
  315. dz->iparam[GR_THISBRKSAMP] = 0;
  316. dz->iparam[GR_NEXTBRKSAMP] = 0;
  317. dz->param[GR_NEXTGATE] = 0;
  318. dz->param[GR_GATESTEP] = 0.0;
  319. dz->iparam[GR_UP] = TRUE;
  320. dz->iparam[GR_TESTLIM] = 0;
  321. }
  322. /************************ CONVERT_SAMPLETIME_TO_SAMPLEGAP ***************************
  323. *
  324. * Store sample count BETWEEN grains in place of times OF grains, and check values!!
  325. */
  326. void convert_sampletime_to_samplegap(dataptr dz)
  327. {
  328. int n, timecnt = 0,bumcnt = 0, grain_moved = 0;
  329. int lval, lastlval = round(dz->parray[GR_SYNCTIME][0]);
  330. int mingap = dz->iparam[GR_ABS_SPLICELEN] * 2;
  331. int minstartgap = dz->iparam[GR_ABS_SPLICELEN];
  332. for(n=1;n<dz->iparam[GR_SYNCCNT];n++) {
  333. lval = round(dz->parray[GR_SYNCTIME][n]);
  334. dz->parray[GR_SYNCTIME][n] = (double)(lval - lastlval);
  335. lastlval = lval;
  336. }
  337. if((lval = minstartgap - round(dz->parray[GR_SYNCTIME][0]))>0) {
  338. if(dz->iparam[GR_SYNCCNT]>1
  339. && (round(dz->parray[GR_SYNCTIME][1]) - lval >= mingap)) {
  340. dz->parray[GR_SYNCTIME][1] -= (double)lval;
  341. dz->parray[GR_SYNCTIME][0] += (double)lval;
  342. fprintf(stdout,"WARNING: 1st grain moved by %lf secs (%d samps) to allow for startsplice\n",
  343. (double)(lval/dz->infile->channels)/(double)dz->infile->srate,lval);
  344. fflush(stdout);
  345. } else {
  346. dz->parray[GR_SYNCTIME][0] = (double)dz->iparam[GR_ABS_SPLICELEN];
  347. fprintf(stdout,"WARNING: All grain times offset by %lf secs (%d samps) to allow for startsplice\n",
  348. (double)(lval/dz->infile->channels)/(double)dz->infile->srate,lval);
  349. fflush(stdout);
  350. }
  351. }
  352. for(n=1;n<dz->iparam[GR_SYNCCNT];n++) {
  353. timecnt++;
  354. if((lval = mingap - round(dz->parray[GR_SYNCTIME][n]))>0) {
  355. bumcnt++;
  356. if(n>1
  357. && (round(dz->parray[GR_SYNCTIME][n-1]) - lval >= mingap)) {
  358. dz->parray[GR_SYNCTIME][n-1] -= (double)lval;
  359. dz->parray[GR_SYNCTIME][n] += (double)lval;
  360. grain_moved++;
  361. } else if (n < dz->iparam[GR_SYNCCNT]-1
  362. && (round(dz->parray[GR_SYNCTIME][n+1]) - lval >= mingap)) {
  363. dz->parray[GR_SYNCTIME][n+1] -= (double)lval;
  364. dz->parray[GR_SYNCTIME][n] += (double)lval;
  365. grain_moved++;
  366. } else {
  367. dz->parray[GR_SYNCTIME][n] = (double)(dz->iparam[GR_ABS_SPLICELEN] * 2);
  368. bumcnt++;
  369. }
  370. }
  371. }
  372. if(bumcnt) {
  373. if(bumcnt >= timecnt/2)
  374. fprintf(stdout,
  375. "WARNING: so many graintimes altered to minimum splicelen that splicetime-frq may produce a tone.\n");
  376. else
  377. fprintf(stdout,"WARNING: (some) set of graintimes shifted to allow for splicetime.\n");
  378. } else if(grain_moved)
  379. fprintf(stdout,"WARNING: %d grain-starttimes moved to allow for splicetime.\n",grain_moved);
  380. fflush(stdout);
  381. }
  382. /*************************** MAKE_GRAIN_SPLICETABLE ***************************/
  383. int make_grain_splicetable(dataptr dz)
  384. {
  385. int n;
  386. int splicelen = dz->iparam[GR_SPLICELEN]/2;
  387. if((dz->parray[GR_SPLICETAB] = (double *)malloc(splicelen * sizeof(double)))==NULL) {
  388. sprintf(errstr,"INSUFFICIENT MEMORY for splice table.\n");
  389. return(MEMORY_ERROR);
  390. }
  391. for(n=0;n<splicelen;n++)
  392. dz->parray[GR_SPLICETAB][n] = (double)n/(double)splicelen;
  393. return FINISHED;
  394. }
  395. /************************* READENV ******************************
  396. *
  397. * Extract envelope values from a buffer of samples.
  398. */
  399. int readenv(int samps_to_process,int winsamps,float *maxsamp,double **winptr,dataptr dz)
  400. {
  401. int startsamp = 0;
  402. double *env = *winptr;
  403. while(samps_to_process >= winsamps) {
  404. *env = getmaxsamp(startsamp,maxsamp,winsamps,dz);
  405. if(++env > dz->ptr[GR_ENVEND]) {
  406. sprintf(errstr,"Array overflow in readenv(): 1\n");
  407. return(PROGRAM_ERROR);
  408. }
  409. startsamp += winsamps;
  410. samps_to_process -= winsamps;
  411. }
  412. if(samps_to_process) { /* Handle any final short buffer */
  413. *env = getmaxsamp(startsamp,maxsamp,winsamps,dz);
  414. if(++env > dz->ptr[GR_ENVEND]) {
  415. sprintf(errstr,"Array overflow in readenv(): 2\n");
  416. return(PROGRAM_ERROR);
  417. }
  418. }
  419. *winptr = env;
  420. return(FINISHED);
  421. }
  422. /*************************** GETMAXSAMP ******************************
  423. *
  424. * Find largest sample over window.
  425. *
  426. * NB We assume that in a stereo file,the largest sample in EITHER channel
  427. * represents the max amplitude.
  428. */
  429. double getmaxsamp(int startsamp,float *maxsamp, int winsamps,dataptr dz)
  430. {
  431. int i, endsamp = startsamp + winsamps;
  432. /*int*/float thismaxsamp = 0.0;
  433. /*int*/double val;
  434. for(i = startsamp; i<endsamp; i++) {
  435. val = fabs(dz->sampbuf[0][i]);
  436. thismaxsamp = (float) max(thismaxsamp,val);
  437. }
  438. if(thismaxsamp > *maxsamp)
  439. *maxsamp = thismaxsamp;
  440. return((double)thismaxsamp);
  441. }
  442. /**************************** NORMALISE_ENV *************************/
  443. int normalise_env(dataptr dz)
  444. {
  445. int n;
  446. double *d = dz->parray[GR_ENVEL];
  447. double scaler;
  448. double maxsamp = 0.0;
  449. for(n=0;n<dz->iparam[GR_WINCNT];n++) {
  450. maxsamp = max(maxsamp,*d);
  451. d++;
  452. }
  453. if(maxsamp==0.0) {
  454. sprintf(errstr,"Zero level in input file.\n");
  455. return(DATA_ERROR);
  456. }
  457. scaler = 1.0/(double)maxsamp;
  458. d = dz->parray[GR_ENVEL];
  459. for(n=0;n<dz->iparam[GR_WINCNT];n++) {
  460. *d *= scaler;
  461. d++;
  462. }
  463. return(FINISHED);
  464. }
  465. /*************************** SEEK_TO_START_AND_ZERO_ALL_COUNTERS *************************/
  466. int seek_to_start_and_zero_all_counters(dataptr dz)
  467. {
  468. if(sndseekEx(dz->ifd[0],0,0)<0) {
  469. sprintf(errstr,"seek failed: seek_to_start_and_zero_all_counters()\n");
  470. return(SYSTEM_ERROR);
  471. }
  472. dz->total_samps_read = 0;
  473. dz->samps_left = dz->insams[0];
  474. return(FINISHED);
  475. }
  476. /**************************** CREATE_ENVSTEPS *************************/
  477. void create_envsteps(dataptr dz)
  478. {
  479. int n;
  480. double sampstep = (double)(dz->iparam[GR_WSIZE_SAMPS]/dz->infile->channels);
  481. for(n=0;n<dz->iparam[GR_WINCNT]-1;n++)
  482. dz->parray[GR_ENVSTEP][n] =
  483. (dz->parray[GR_ENVEL][n+1] - dz->parray[GR_ENVEL][n])/(double)sampstep;
  484. dz->parray[GR_ENVSTEP][n] = 0.0;
  485. }