envel.c 50 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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 <string.h>
  25. #include <structures.h>
  26. #include <tkglobals.h>
  27. #include <globcon.h>
  28. #include <processno.h>
  29. #include <modeno.h>
  30. #include <arrays.h>
  31. #include <envel.h>
  32. #include <cdpmain.h>
  33. //TW UPDATE
  34. #include <logic.h>
  35. #include <limits.h>
  36. #include <osbind.h>
  37. #include <sfsys.h>
  38. #define INBUF_START (0)
  39. #define OUTBUF_START (1)
  40. #define OUTBUF_END (2)
  41. //#ifdef unix
  42. #define round(x) lround((x))
  43. //#endif
  44. static int init_outbuf
  45. (int startsamp,int *is_simple,int *write_offset,int *samp_offset,int *samps_left_to_process,dataptr dz);
  46. static int init_brkpnts
  47. (int *sampno,double *starttime,double *gain,double **endbrk,double **nextbrk,
  48. double *nextgain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz);
  49. static int advance_brkpnts
  50. (double starttime,double *gain,double *endbrk,double **nextbrk,double *nextgain,
  51. double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz);
  52. static int calc_samps_to_process
  53. (int *startsamp,int *samps_left_to_process,dataptr dz);
  54. static int simple_envel_processing
  55. (int *samps_left_to_process,double starttime,double *endbrk,double **nextbrk,double *nextgain,
  56. int *sampno,double *gain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz);
  57. static int buf_staggered_envel_processing
  58. (int *samps_left_to_process,int samp_offset,int write_offset,double starttime,double *endbrk,double **nextbrk,
  59. double *nextgain,int *sampno,double *gain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz);
  60. static int read_partbuf_samps
  61. (int samps_to_read,int *samps_left_to_process, dataptr dz);
  62. static int do_envelope
  63. (int samp_cnt,double starttime,double *endbrk,double **nextbrk,double *nextgain,
  64. int *sampno,double *gain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz);
  65. static int read_ssamps(int samps_to_read,int *samps_left_to_process,dataptr dz);
  66. static int do_simple_read(int *samps_left_to_process,int bufsize,dataptr dz);
  67. static int do_offset_read(int *samps_left_to_process,int samp_offset,int bufsize,dataptr dz);
  68. static int skip_into_file(int startsamp,int extended_buf_sampsize,int *write_offset,int *samp_offset,dataptr dz);
  69. /******************************* APPLY_BRKPNT_ENVELOPE *******************************/
  70. int apply_brkpnt_envelope(dataptr dz)
  71. {
  72. int exit_status;
  73. int startsamp, samps_left_to_process;
  74. int is_simple;
  75. int write_offset, samp_offset, sampno, nextbrk_sampno;
  76. double starttime, gain, nextgain, gain_step, gain_incr;
  77. double *endbrk, *nextbrk;
  78. if((exit_status = calc_samps_to_process(&startsamp,&samps_left_to_process,dz))<0)
  79. return(exit_status);
  80. if((exit_status = init_outbuf(startsamp,&is_simple,&write_offset,&samp_offset,&samps_left_to_process,dz))<0)
  81. return(exit_status);
  82. if((exit_status = init_brkpnts
  83. (&sampno,&starttime,&gain,&endbrk,&nextbrk,&nextgain,&gain_step,&gain_incr,&nextbrk_sampno,dz))<0)
  84. return(exit_status);
  85. exit_status = FINISHED;
  86. if(is_simple)
  87. exit_status = simple_envel_processing
  88. (&samps_left_to_process,starttime,endbrk,&nextbrk,&nextgain,
  89. &sampno,&gain,&gain_step,&gain_incr,&nextbrk_sampno,dz);
  90. else
  91. exit_status = buf_staggered_envel_processing
  92. (&samps_left_to_process,samp_offset,write_offset,starttime,endbrk,&nextbrk,
  93. &nextgain,&sampno,&gain,&gain_step,&gain_incr,&nextbrk_sampno,dz);
  94. return(exit_status);
  95. }
  96. /**************************** INIT_OUTBUF *******************************
  97. *
  98. * |-------------extended-buffer-size-----------|
  99. * X
  100. * |-------------buffer-size---------------|
  101. * INBUF
  102. * |----|----|----|----|----|----|----|----|----|
  103. * | | |
  104. * | | | |
  105. write (=write
  106. offset offset)
  107. * | | | |
  108. * | | |
  109. * samp |
  110. * offset |
  111. * | | |
  112. * |----|----|----|----|----|----|----|----|
  113. * OUTBUF
  114. * |-------------buffer-size---------------|
  115. *
  116. * IF the brkpoint table starts at 0,
  117. * we can use THE SAME buffer for input and output.
  118. * OTHERWISE.........
  119. * (8) First extimate of the number of samples in the input file which
  120. * we can skip, i.e. the number of complete extended-buffer-fulls
  121. * (see diagram) we can read before reaching first significant sample.
  122. * (9) After counting out these, we can assess how many COMPLETED sectors
  123. * are still to be read and ignored.
  124. * (10) We can now add the number of samples in these sectors to our first
  125. * estimate of samples to be skipped.
  126. * (11) The extent to which the OUTPUT buffer will be offset from the
  127. * INPUT buffer, (samp_offset) is given by the remaining part-sector of samps.
  128. * (see diagram).
  129. * (12) After the initial write, we will WRITE to a block 1 SECTOR later,
  130. * (X in diagram), so the WRITE-OFFSET is as shown.
  131. * (13) We now SEEK an exact number of sectors in the input file (thus
  132. * discarding these samps from our processing).
  133. * (14) If the samp_offset is ZERO, then we input and output buffers are
  134. * the same as at 4,5,6.
  135. * (16) Otherwise, fill the EXTENDED buffer (see diagram).
  136. * (17) Move the address of future read-ins (inbuf) 1 sector forward (to X in diagram).
  137. * (18) Set the address of the read-out buffer at the correct offset.
  138. * (19) Set the flag for the more difficult case.
  139. * (20) Decrement number of samps left to process.
  140. * If this takes samps_left below zero, this means we have
  141. * read a whole sector in place of a part-sector, so we must
  142. * readjust the value of samps_read!!
  143. */
  144. int init_outbuf(int startsamp,int *is_simple,int *write_offset,
  145. int *samp_offset,int *samps_left_to_process,dataptr dz)
  146. {
  147. int exit_status;
  148. int extended_buf_sampsize = dz->buflen;
  149. int shsecsize = F_SECSIZE;
  150. /*RWD: set the vars*/
  151. *samp_offset = *write_offset = 0;
  152. if(startsamp==0) { /* If we start at beginning */
  153. dz->sampbuf[OUTBUF_START] = dz->sampbuf[INBUF_START]; /* inbuf and outbuf coincide */
  154. if((exit_status = do_simple_read(samps_left_to_process,dz->buflen,dz))<0)
  155. return(exit_status); /* setup simple buffering option */
  156. *is_simple = TRUE;
  157. } else {
  158. if((exit_status = skip_into_file(startsamp,extended_buf_sampsize,write_offset,samp_offset,dz))<0)
  159. return(exit_status); /* calculate sectors to skip into file, and any part-sector offset, and skip */
  160. if(*samp_offset==0) { /* If no offset */
  161. dz->sampbuf[OUTBUF_START] = dz->sampbuf[INBUF_START];/* inbuf and outbuf coincide */
  162. if((exit_status = do_simple_read(samps_left_to_process,dz->buflen,dz))<0)
  163. return(exit_status);
  164. *is_simple = TRUE;
  165. } else { /* Otherwise there is an offset */
  166. if((exit_status = do_offset_read(samps_left_to_process,*samp_offset,
  167. /*dz->bigbufsize + SECSIZE*/dz->buflen,dz))<0)
  168. return(exit_status); /* read initial LARGE buffer */
  169. dz->sampbuf[OUTBUF_START] = dz->sampbuf[INBUF_START] + *samp_offset;
  170. /* Set outbuf (write) position */
  171. dz->sampbuf[OUTBUF_END] = dz->sampbuf[OUTBUF_START] + dz->buflen;
  172. /* Set endpointer of outbuf */
  173. dz->sampbuf[INBUF_START] += shsecsize; /* Set next read position for inbuf */
  174. /* to permit correct wrap_around of part_sector */
  175. *is_simple = FALSE; /* Flag staggerd-buffers option */
  176. }
  177. }
  178. return(FINISHED);
  179. }
  180. /**************************** INIT_BRKPNTS *******************************
  181. * NB Here samples are taken to be a short for mono, 2 shorts for stereo, etc.
  182. * and times are measured in such 'samples'.
  183. */
  184. int init_brkpnts(int *sampno,double *starttime,double *gain,double **endbrk,double **nextbrk,
  185. double *nextgain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz)
  186. {
  187. double nexttime, time_from_start;
  188. int paramno = dz->extrabrkno;
  189. *endbrk = dz->brk[paramno] + ((dz->brksize[paramno]-1) * 2);
  190. *sampno = 0;
  191. *starttime = dz->brk[paramno][0];
  192. *gain = dz->brk[paramno][1];
  193. *nextbrk = dz->brk[paramno] + 2;
  194. nexttime = **nextbrk;
  195. *nextgain = *((*nextbrk) + 1);
  196. *gain_step = *nextgain - *gain;
  197. time_from_start = nexttime - *starttime;
  198. /* OCT 1996 */
  199. if((*nextbrk_sampno = (int)round(time_from_start * (double)dz->infile->srate))<0) {
  200. sprintf(errstr,"Impossible brkpoint time: (%.2lf secs)\n",time_from_start);
  201. return(PROGRAM_ERROR);
  202. }
  203. *gain_incr = (*gain_step)/(double)(*nextbrk_sampno);
  204. return(FINISHED);
  205. }
  206. /**************************** ADVANCE_BRKPNTS *****************************
  207. * NB Here samples are taken to be a short for mono, 2 shorts for stereo, etc.
  208. * and times are measured in such 'samples'.
  209. */
  210. int advance_brkpnts(double starttime,double *gain,double *endbrk,double **nextbrk,
  211. double *nextgain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz)
  212. {
  213. double nexttime, time_from_start;
  214. int lastbrk_sampno, sampdist;
  215. if(*nextbrk!=endbrk) {
  216. *nextbrk += 2;
  217. *gain = *nextgain;
  218. nexttime = **nextbrk;
  219. *nextgain = *((*nextbrk) + 1);
  220. *gain_step = *nextgain - *gain;
  221. lastbrk_sampno = *nextbrk_sampno;
  222. time_from_start = nexttime - starttime;
  223. /* OCT 1996 */
  224. if((*nextbrk_sampno = (int)round(time_from_start * dz->infile->srate))<0) {
  225. sprintf(errstr,"Impossible brkpoint time: (%.2lf secs)\n",time_from_start);
  226. return(PROGRAM_ERROR);
  227. }
  228. sampdist = *nextbrk_sampno - lastbrk_sampno;
  229. *gain_incr = (*gain_step)/(double)sampdist;
  230. }
  231. return(FINISHED);
  232. }
  233. /************************ CALC_SAMPS_TO_PROCESS ****************************
  234. *
  235. * (1) Find time of final breakpoint value.
  236. * (a) Find the sample position of the brkpoint-table's starting time.
  237. * (b) Find its samp position.
  238. * (2) Find this time in samples (here samples mean short samples).
  239. * (3) The last samp to be processed is either the samp corresponding
  240. * to the last sample-time in brkpnt file OR the end of the input file.
  241. * (4) Number of samps-to-process = endsamp-time - startsamp-time.
  242. * (5) This also gives the required size of output file.
  243. */
  244. int calc_samps_to_process(int *startsamp,int *samps_left_to_process,dataptr dz)
  245. {
  246. int paramno = dz->extrabrkno;
  247. int endbrk_samptime, endsamp, start_samp;
  248. double lastbrktime, firstbrktime;
  249. double infiledur = (double)(dz->insams[0]/dz->infile->channels)/(double)dz->infile->srate;
  250. lastbrktime = *(dz->brk[paramno] + ((dz->brksize[paramno] - 1) * 2));
  251. if(flteq(lastbrktime,infiledur)) {
  252. endsamp = dz->insams[0];
  253. } else {
  254. endbrk_samptime = round(lastbrktime * (double)dz->infile->srate);
  255. endbrk_samptime *= dz->infile->channels;
  256. endsamp = min((int)endbrk_samptime,dz->insams[0]);
  257. }
  258. firstbrktime = *(dz->brk[paramno]);
  259. *startsamp = round(firstbrktime * (double)dz->infile->srate);
  260. *startsamp *= dz->infile->channels;
  261. if((start_samp = *startsamp ) >= dz->insams[0]) {
  262. sprintf(errstr,"envelope begins after end of file: can't proceed.\n");
  263. return(DATA_ERROR);
  264. }
  265. *samps_left_to_process = endsamp - start_samp;
  266. return(FINISHED);
  267. }
  268. /*********************** SIMPLE_ENVEL_PROCESSING ********************************
  269. *
  270. * Simple case, input and output buffers coincide.
  271. *
  272. * (1) If we read beyond number of samps we anticipated, this means
  273. * we have read to the end of a sector, where we need a part-sector,
  274. * so we must adjust value of actual samps read!!!
  275. */
  276. int simple_envel_processing
  277. (int *samps_left_to_process,double starttime,double *endbrk,double **nextbrk,double *nextgain,
  278. int *sampno,double *gain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz)
  279. {
  280. int exit_status;
  281. while(*samps_left_to_process > 0) {
  282. if((exit_status = do_envelope
  283. (dz->buflen,starttime,endbrk,nextbrk,nextgain,sampno,gain,gain_step,gain_incr,nextbrk_sampno,dz))<0)
  284. return(exit_status);
  285. if((exit_status = write_samps(dz->sampbuf[OUTBUF_START],dz->buflen,dz))<0)
  286. return(exit_status);
  287. if((exit_status = do_simple_read(samps_left_to_process,dz->buflen,dz))<0)
  288. return(exit_status);
  289. }
  290. if((exit_status = do_envelope
  291. (dz->ssampsread,starttime,endbrk,nextbrk,nextgain,sampno,gain,gain_step,gain_incr,nextbrk_sampno,dz))<0)
  292. return(exit_status);
  293. if(dz->ssampsread > 0)
  294. return write_samps(dz->sampbuf[OUTBUF_START],dz->ssampsread,dz);
  295. return(FINISHED);
  296. }
  297. /*********************** BUF_STAGGERED_ENVEL_PROCESSING ********************************
  298. *
  299. * Non-simple case, input and output buffers do not coincide.
  300. *
  301. * ___________tail is copied thus_________
  302. * | |
  303. * | |
  304. * v INBUF ^
  305. * |----|----|----|----|----|----|----|----|----|
  306. * | |
  307. * | | | |
  308. * write_offset tail
  309. * | | | |
  310. * | |
  311. * |----|----|----|----|----|----|----|----|
  312. * OUTBUF
  313. *
  314. * (1) If we are inside the loop, there are still samps left to read
  315. * from input file, so this input buffer must be FULL.
  316. * This means we can WRITE a full output-buffer.
  317. * (2) Copy the tail-portion of the input buffer (that falls outside the
  318. * end of the output buffer (see diagram)), to the start of the output
  319. buffer (see diagram).
  320. * (3) Read samps to inbuf location, decrementing no of samps left to read.
  321. * (4) If first time, (No buffers written: samps were read into VERY START of buf)
  322. * no. of samps to write equals samps_read
  323. * MINUS those not needed, in samp_offset area.....
  324. * (5) After first time, (Buffers laready writ: samps now read into the displaced inbuf)
  325. * number of samps to write equals those read
  326. * PLUS those already in start of outbuffer, haing been copied back into the write_offset segment.
  327. * (6) Do envelope on the incomplete (or exactly full) buffer.
  328. * (7) Write this.
  329. */
  330. int buf_staggered_envel_processing
  331. (int *samps_left_to_process,int samp_offset,int write_offset,double starttime,double *endbrk,double **nextbrk,
  332. double *nextgain,int *sampno,double *gain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz)
  333. {
  334. int exit_status;
  335. int samps_to_write_here;
  336. int firstime = TRUE;
  337. while(*samps_left_to_process > 0) {
  338. firstime = FALSE;
  339. if((exit_status = do_envelope
  340. (dz->buflen,starttime,endbrk,nextbrk,nextgain,sampno,gain,gain_step,gain_incr,nextbrk_sampno,dz))<0)
  341. return(exit_status);
  342. if((exit_status = write_samps(dz->sampbuf[OUTBUF_START],dz->buflen,dz))<0)
  343. return(exit_status); /* 1 */
  344. memmove((char *)dz->sampbuf[OUTBUF_START],(char *)dz->sampbuf[OUTBUF_END],write_offset * sizeof(float));
  345. if((exit_status = do_simple_read(samps_left_to_process,dz->buflen,dz))<0)
  346. return(exit_status); /* 3 */
  347. }
  348. if(firstime)
  349. samps_to_write_here = dz->ssampsread - samp_offset; /* 4 */
  350. else
  351. samps_to_write_here = dz->ssampsread + write_offset; /* 5 */
  352. if((exit_status = do_envelope /* 6 */
  353. (samps_to_write_here,starttime,endbrk,nextbrk,nextgain,sampno,gain,gain_step,gain_incr,nextbrk_sampno,dz))<0)
  354. return(exit_status);
  355. /* 7 */
  356. if(samps_to_write_here > 0)
  357. return write_samps(dz->sampbuf[OUTBUF_START],samps_to_write_here,dz);
  358. return(FINISHED);
  359. }
  360. /**************************** READ_PARTBUF_SAMPS *****************************/
  361. int read_partbuf_samps(int samps_to_read,int *samps_left_to_process, dataptr dz)
  362. {
  363. if((dz->ssampsread = fgetfbufEx(dz->sampbuf[INBUF_START], samps_to_read,dz->ifd[0],0)) < 0) {
  364. sprintf(errstr,"Can't read samples from input soundfile: read_partbuf_samps()\n");
  365. return(SYSTEM_ERROR);
  366. }
  367. if(dz->ssampsread < samps_to_read) {
  368. sprintf(errstr,"Error in buffering arithmetic: read_partbuf_samps()\n");
  369. return(PROGRAM_ERROR);
  370. }
  371. *samps_left_to_process -= dz->ssampsread;
  372. return(FINISHED);
  373. }
  374. /************************* DO_ENVELOPE ********************************
  375. *
  376. * (1) endsampno (absolute numbering) is the final sample to be treated in this call.
  377. *
  378. * While ever the quit-flag is not set...
  379. * (2) if the sample number of the next break-pnt falls before or at the end
  380. * of this function call...
  381. * Set the 'change' flag, which will cause envelope breakpoints to be
  382. * advanced.
  383. * (3) set end of the inner-loop pass to this next brkpnt.
  384. * (4) If the brkpnt falls exactly at end of pass, set the 'quit' flag.
  385. * Otherwise quit remains FALSE, and the outer loop will be recalled (after
  386. * breakpoints have been advanced).
  387. * (5) Otherwise, the next breakpnt falls beyond the end of this function call.
  388. * So don't advance the breakpoints (change = FALSE), sample at end of inner
  389. * loop (this_endsamp) is the sample at end of this call-to-function
  390. * (endsampno), AND set flag to quit at end of inner loop.
  391. * (6) Counter for inner loop is this-endsamp minus current position (sampno).
  392. * (7) Inner loop, get gain for each sample, and increment samples accordingly.
  393. * (8) Increment the absolute count of processed samples (sampno).
  394. * (9) If change flag is set, reset gain and advance breakpoints.
  395. * (10) Retain the enveloping gain current at end of buffer.
  396. */
  397. int do_envelope
  398. (int samp_cnt,double starttime,double *endbrk,double **nextbrk,double *nextgain,
  399. int *sampno,double *gain,double *gain_step,double *gain_incr,int *nextbrk_sampno,dataptr dz)
  400. {
  401. int exit_status;
  402. int n, m, sampcnt;
  403. int endsampno, this_endsamp, this_sampcnt;
  404. float *obuf = dz->sampbuf[OUTBUF_START];
  405. float *obufend = obuf + dz->buflen;
  406. int quit = FALSE, change;
  407. double val;
  408. double this_gain = *gain;
  409. double this_gain_incr = *gain_incr;
  410. double this_gain_step = *gain_step;
  411. sampcnt = samp_cnt / dz->infile->channels; /* 'stereo'-samples to process */
  412. endsampno = *sampno + sampcnt; /* 1 */
  413. if(sampcnt * dz->infile->channels > dz->buflen) {
  414. sprintf(errstr,"Buffering anomaly: do_envelope()\n");
  415. return(PROGRAM_ERROR);
  416. }
  417. while(quit==FALSE) {
  418. if(*nextbrk_sampno <= endsampno) { /* 2 */
  419. change = TRUE;
  420. this_endsamp = *nextbrk_sampno; /* 3 */
  421. if(*nextbrk_sampno==endsampno)
  422. quit = TRUE; /* 4 */
  423. } else {
  424. change = FALSE; /* 5 */
  425. this_endsamp = endsampno;
  426. quit = TRUE;
  427. }
  428. this_sampcnt = this_endsamp - *sampno; /* 6 */
  429. if(obuf + (this_sampcnt * dz->infile->channels) > obufend) {
  430. sprintf(errstr,"array overrun: do_envelope()\n");
  431. return(PROGRAM_ERROR);
  432. }
  433. if(flteq(this_gain,1.0) && flteq(this_gain_step,0.0))
  434. obuf += this_sampcnt * dz->infile->channels; /* no modification of sound */
  435. else {
  436. for(n=0;n<this_sampcnt;n++) { /* 7 */
  437. this_gain += this_gain_incr;
  438. for(m=0;m<dz->infile->channels;m++) {
  439. val = /*round*/((double)(*obuf) * this_gain);
  440. *obuf = (float)val;
  441. obuf++;
  442. }
  443. }
  444. }
  445. *sampno += this_sampcnt; /* 8 */
  446. if(change) { /* 9 */
  447. if((exit_status = advance_brkpnts
  448. (starttime,gain,endbrk,nextbrk,nextgain,gain_step,gain_incr,nextbrk_sampno,dz))<0)
  449. return(exit_status);
  450. this_gain = *gain;
  451. this_gain_incr = *gain_incr;
  452. this_gain_step = *gain_step;
  453. }
  454. }
  455. *gain = this_gain; /* 10 */
  456. return(FINISHED);
  457. }
  458. /************************* READ_SSAMPS ******************************/
  459. int read_ssamps(int samps_to_read,int *samps_left_to_process,dataptr dz)
  460. {
  461. if((dz->ssampsread = fgetfbufEx(dz->sampbuf[INBUF_START], samps_to_read,dz->ifd[0],0)) < 0) {
  462. sprintf(errstr,"Can't read samples from input soundfile: read_ssamps()\n");
  463. return(SYSTEM_ERROR);
  464. }
  465. if(dz->ssampsread!=samps_to_read) {
  466. sprintf(errstr,"Error in buffering arithmetic: read_ssamps()\n");
  467. return(PROGRAM_ERROR);
  468. }
  469. *samps_left_to_process -= dz->ssampsread;
  470. return(FINISHED);
  471. }
  472. /******************************** DO_SIMPLE_READ **********************************/
  473. int do_simple_read(int *samps_left_to_process,int bufsize,dataptr dz)
  474. {
  475. int exit_status;
  476. if(*samps_left_to_process < bufsize)
  477. exit_status = read_partbuf_samps(*samps_left_to_process,samps_left_to_process,dz);
  478. else
  479. exit_status = read_ssamps(bufsize,samps_left_to_process,dz);
  480. return(exit_status);
  481. }
  482. /******************************** DO_OFFSET_READ **********************************/
  483. int do_offset_read(int *samps_left_to_process,int samp_offset,int bufsize,dataptr dz)
  484. {
  485. int exit_status;
  486. if(*samps_left_to_process < bufsize) {
  487. exit_status = read_partbuf_samps(*samps_left_to_process + samp_offset,samps_left_to_process,dz);
  488. *samps_left_to_process = 0;
  489. } else {
  490. exit_status = read_ssamps(bufsize,samps_left_to_process,dz);
  491. *samps_left_to_process += samp_offset; /* some of samps-read are not part of samps-to-process */
  492. }
  493. return(exit_status);
  494. }
  495. /******************************** SKIP_INTO_FILE **********************************/
  496. //RWD ugh! unless this is simply a sndseek to startsamp....
  497. //TW unfortunately, it's intrinsically tied up with old buffering scheme
  498. //#ifdef NOTDEF
  499. int skip_into_file(int startsamp,int extended_buf_sampsize,int *write_offset,int *samp_offset,dataptr dz)
  500. {
  501. int skipsamps=(startsamp/extended_buf_sampsize) * extended_buf_sampsize; /* 8 */
  502. int sampsecsize = ENV_FSECSIZE;
  503. int sectors_remaining = (startsamp - skipsamps)/sampsecsize; /* 9 */
  504. skipsamps += sectors_remaining * sampsecsize; /* 10 */
  505. *samp_offset = startsamp - skipsamps; /* 11 */
  506. *write_offset = ENV_FSECSIZE - *samp_offset; /* 12 */
  507. if(sndseekEx(dz->ifd[0],skipsamps,0)<0) { /* 13 */
  508. sprintf(errstr,": sndseekEx failed: skip_into_file()\n");
  509. return(SYSTEM_ERROR);
  510. }
  511. return(FINISHED);
  512. }
  513. //#endif
  514. //TW UPDATE: NEW CODE
  515. /*** NEW april 2002 ****/
  516. static int fill_grid_array(double starttime,int *firstpass, double *next_gridstart, double **d, int *arraysize, dataptr dz);
  517. static int check_available_space(dataptr dz);
  518. static int create_grid_envelope(int n, double *next_gridstart,dataptr dz);
  519. static int do_grid_envelope(dataptr dz);
  520. static int do_grid_biz(int sib,int eib,int style,int *splicepos,dataptr dz);
  521. static void get_nextposition_pair(double *ds,int *startsamp,int *endsamp,int *style,dataptr dz);
  522. #define GRID_ZERO (0)
  523. #define GRID_COPY (1)
  524. #define GRID_DOWN (2)
  525. #define GRID_UP (3)
  526. /************************************ DO_GRIDS ********************************/
  527. int do_grids(dataptr dz)
  528. {
  529. int exit_status;
  530. int n;
  531. int namelen, numlen;
  532. char *outfilename;
  533. //TW REVISION DEc 2002
  534. // char *outfilenumber;
  535. char *p, *q, *r;
  536. double next_gridstart;
  537. numlen = 4;
  538. if(!sloom) {
  539. namelen = strlen(dz->wordstor[0]);
  540. q = dz->wordstor[0];
  541. r = dz->wordstor[0] + namelen;
  542. p = r - 1;
  543. while((*p != '\\') && (*p != '/') && (*p != ':')) {
  544. p-- ;
  545. if(p < dz->wordstor[0])
  546. break;
  547. }
  548. if(p > dz->wordstor[0]) {
  549. p++;
  550. while(p <= r)
  551. *q++ = *p++;
  552. }
  553. }
  554. namelen = strlen(dz->wordstor[0]);
  555. // if(sndunlink(dz->ofd) < 0) {
  556. // fprintf(stdout,"WARNING: Can't set initial dummy output soundfile for deletion.\n");
  557. // fflush(stdout);
  558. // }
  559. // if(sndcloseEx(dz->ofd) < 0) {
  560. // fprintf(stdout,"ERROR: Can't close initial dummy output soundfile\n");
  561. // return(SYSTEM_ERROR);
  562. // }
  563. dz->ofd = -1;
  564. if((exit_status = check_available_space(dz))<0)
  565. return(exit_status);
  566. if((dz->tempsize = dz->insams[0] * dz->iparam[GRID_COUNT])<0)
  567. dz->tempsize = INT_MAX;
  568. if(sloom)
  569. namelen--; /* Drop the 0 at end of name */
  570. next_gridstart = 0.0;
  571. if((exit_status = reset_peak_finder(dz))<0)
  572. return(exit_status);
  573. for(n=0;n<dz->iparam[GRID_COUNT];n++) {
  574. if(sndseekEx(dz->ifd[0],0,0)<0) {
  575. sprintf(errstr,"sndseekEx() failed.\n");
  576. return(SYSTEM_ERROR);
  577. }
  578. reset_filedata_counters(dz);
  579. // FEB 2010 TW
  580. if((outfilename = (char *)malloc((namelen + numlen + 10) * sizeof(char)))==NULL) {
  581. sprintf(errstr,"INSUFFICIENT MEMORY for outfilename.\n");
  582. return(MEMORY_ERROR);
  583. }
  584. strcpy(outfilename,dz->wordstor[0]);
  585. //TW REvision Dec 2002
  586. if(sloom)
  587. insert_new_number_at_filename_end(outfilename,n,1);
  588. // FEB 2010 TW
  589. else {
  590. insert_separator_on_sndfile_name(outfilename,1);
  591. insert_new_number_at_filename_end(outfilename,n,0);
  592. }
  593. dz->process_type = EQUAL_SNDFILE; /* allow sndfile to be created */
  594. if((exit_status = create_sized_outfile(outfilename,dz))<0) {
  595. if(!sloom) {
  596. sprintf(errstr, "Soundfile %s already exists: Made %d grids only.\n",outfilename,n-1);
  597. free(outfilename);
  598. dz->process_type = OTHER_PROCESS;
  599. dz->ofd = -1;
  600. return(GOAL_FAILED);
  601. } else {
  602. dz->process_type = OTHER_PROCESS;
  603. dz->ofd = -1;
  604. sprintf(errstr, "Soundfile %s already exists: Made %d grids only.\n",outfilename,n-1);
  605. return(SYSTEM_ERROR);
  606. }
  607. }
  608. dz->process_type = OTHER_PROCESS;
  609. if((exit_status = create_grid_envelope(n,&next_gridstart,dz))<0)
  610. return(exit_status);
  611. if((exit_status = do_grid_envelope(dz))<0)
  612. return(exit_status);
  613. dz->process_type = EQUAL_SNDFILE; /* allows header to be written */
  614. dz->outfiletype = SNDFILE_OUT; /* allows header to be written */
  615. if((exit_status = headwrite(dz->ofd,dz))<0) {
  616. free(outfilename);
  617. return(exit_status);
  618. }
  619. dz->process_type = OTHER_PROCESS; /* restore true status */
  620. dz->outfiletype = NO_OUTPUTFILE; /* restore true status */
  621. if((exit_status = reset_peak_finder(dz))<0)
  622. return(exit_status);
  623. if(sndcloseEx(dz->ofd) < 0) {
  624. fprintf(stdout,"WARNING: Can't close output soundfile %s\n",outfilename);
  625. fflush(stdout);
  626. }
  627. free(outfilename);
  628. dz->ofd = -1;
  629. }
  630. return(FINISHED);
  631. }
  632. /************************************ CHECK_AVAILABLE_SPACE ********************************/
  633. #define LEAVESPACE (10*1024)
  634. int check_available_space(dataptr dz)
  635. {
  636. unsigned int slots;
  637. unsigned int freespace = getdrivefreespace("temp") - LEAVESPACE;
  638. freespace /= sizeof(float);
  639. slots = freespace/dz->insams[0];
  640. if(slots < (unsigned int)dz->iparam[COPY_CNT]) {
  641. sprintf(errstr,"Insufficient space on disk to create %d copies.\n"
  642. "You have space for %d copies.\n",dz->iparam[COPY_CNT],slots);
  643. return(GOAL_FAILED);
  644. }
  645. return(FINISHED);
  646. }
  647. /************************************ CREATE_GRID_ENVELOPE ********************************/
  648. int create_grid_envelope(int n, double *next_gridstart,dataptr dz)
  649. {
  650. double *d, time, thistime, grid_step, half_gridsplen;
  651. int arraysize = 8, old_arraysize;
  652. double starttime;
  653. int firstpass, exit_status;
  654. if(dz->brksize[GRID_WIDTH] == 0) {
  655. grid_step = dz->param[GRID_WIDTH] * dz->iparam[GRID_COUNT];
  656. switch(n) {
  657. case(0):
  658. if((dz->parray[0] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
  659. sprintf(errstr,"Insufficient memory for grid envelope,\n");
  660. return(MEMORY_ERROR);
  661. }
  662. d = dz->parray[0];
  663. for(time = 0.0; time <= dz->duration; time += grid_step) {
  664. thistime = time;
  665. if(flteq(time,0.0))
  666. *d++ = thistime;
  667. else {
  668. if(dz->brksize[GRID_SPLEN] > 0)
  669. read_value_from_brktable(thistime,GRID_SPLEN,dz);
  670. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  671. *d++ = thistime + half_gridsplen;
  672. }
  673. *d++ = 1.0;
  674. thistime += dz->param[GRID_WIDTH];
  675. if(dz->brksize[GRID_SPLEN] > 0)
  676. read_value_from_brktable(thistime,GRID_SPLEN,dz);
  677. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  678. *d++ = thistime - half_gridsplen;
  679. *d++ = 1.0;
  680. *d++ = thistime + half_gridsplen;
  681. *d++ = 0.0;
  682. thistime = time + grid_step;
  683. if(dz->brksize[GRID_SPLEN] > 0) {
  684. read_value_from_brktable(thistime,GRID_SPLEN,dz);
  685. }
  686. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  687. *d++ = thistime - half_gridsplen;
  688. *d++ = 0.0;
  689. old_arraysize = arraysize;
  690. arraysize += 8;
  691. if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],arraysize * sizeof(double)))==NULL) {
  692. sprintf(errstr,"Insufficient memory for grid envelope,\n");
  693. return(MEMORY_ERROR);
  694. }
  695. d = dz->parray[0] + old_arraysize;
  696. dz->parray[1] = d; /* mark end of parray */
  697. }
  698. break;
  699. case(1):
  700. for(d = dz->parray[1]-2; d >= dz->parray[0];d -= 2) {
  701. *(d+4) = (*d) + dz->param[GRID_WIDTH]; /* add time to values, and shift them up two brkpnt places */
  702. *(d+5) = *(d+1);
  703. }
  704. *(dz->parray[0]) = 0.0; /* Insert a zero time zero val */
  705. *(dz->parray[0]+1) = 0.0;
  706. if(dz->brksize[GRID_SPLEN] > 0) { /* And a splice-start zero */
  707. read_value_from_brktable(*(dz->parray[0]+4),GRID_SPLEN,dz);
  708. }
  709. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  710. *(dz->parray[0]+2) = *(dz->parray[0]+4) - half_gridsplen;
  711. *(dz->parray[0]+3) = 0.0;
  712. *(dz->parray[0]+4) += half_gridsplen;
  713. dz->parray[1] += 4; /* mark end of parray */
  714. break;
  715. default: /* move grid by grid-width, except zerotime point */
  716. for(d = dz->parray[1]-2; d >= dz->parray[0]+2;d -= 2)
  717. *d += dz->param[GRID_WIDTH];
  718. break;
  719. }
  720. } else {
  721. switch(n) {
  722. case(0):
  723. starttime = 0.0;
  724. firstpass = 1;
  725. if((dz->parray[0] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
  726. sprintf(errstr,"Insufficient memory for grid envelope,\n");
  727. return(MEMORY_ERROR);
  728. }
  729. d = dz->parray[0];
  730. if((exit_status = fill_grid_array(starttime,&firstpass,next_gridstart,&d,&arraysize,dz))<0)
  731. return(exit_status);
  732. arraysize += 64; /* safety */
  733. if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],arraysize * sizeof(double)))==NULL) {
  734. sprintf(errstr,"Insufficient memory for grid envelope,\n");
  735. return(MEMORY_ERROR);
  736. }
  737. break;
  738. default: /* move grid by grid-width, except zerotime point */
  739. arraysize = 12;
  740. starttime = *next_gridstart;
  741. firstpass = 1;
  742. d = dz->parray[0] + 4;
  743. if((exit_status = fill_grid_array(starttime,&firstpass,next_gridstart,&d,&arraysize,dz))<0)
  744. return(exit_status);
  745. *(dz->parray[0]) = 0.0; /* Insert a zero time zero val */
  746. *(dz->parray[0]+1) = 0.0;
  747. if(dz->brksize[GRID_SPLEN] > 0) /* And a splice-start zero */
  748. read_value_from_brktable(*(dz->parray[0]+4),GRID_SPLEN,dz);
  749. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  750. *(dz->parray[0]+2) = *(dz->parray[0]+4) - half_gridsplen;
  751. *(dz->parray[0]+3) = 0.0;
  752. *(dz->parray[0]+4) += half_gridsplen;
  753. break;
  754. }
  755. }
  756. return(FINISHED);
  757. }
  758. /************************************ FILL_GRID_ARRAY ********************************/
  759. int fill_grid_array(double starttime,int *firstpass, double *next_gridstart, double **d, int *arraysize, dataptr dz)
  760. {
  761. double grid_step = 0.0, time, thistime, start_gridwidth, this_gridwidth, half_gridsplen = 0.0;
  762. int z;
  763. int k; //old_arraysize;
  764. for(time = starttime; time <=dz->duration; time += grid_step) {
  765. grid_step = 0.0;
  766. thistime = time;
  767. read_value_from_brktable(thistime,GRID_WIDTH,dz);
  768. start_gridwidth = dz->param[GRID_WIDTH];
  769. if(*firstpass) /* save initial distance to next grid set */
  770. *next_gridstart += start_gridwidth;
  771. this_gridwidth = start_gridwidth;
  772. grid_step += this_gridwidth;
  773. thistime += this_gridwidth;
  774. for(z=1;z<dz->iparam[GRID_COUNT];z++) { /*sum steps of all grids to get step from */
  775. read_value_from_brktable(thistime,GRID_WIDTH,dz); /* current window of this grid, to next window of this grid */
  776. this_gridwidth = dz->param[GRID_WIDTH];
  777. grid_step += this_gridwidth;
  778. thistime += this_gridwidth;
  779. }
  780. thistime = time;
  781. if(*firstpass)
  782. half_gridsplen = 0.0; /* Envelope starts without splice ... splice added in calling routine */
  783. else if(dz->brksize[GRID_SPLEN] > 0) {
  784. read_value_from_brktable(thistime,GRID_SPLEN,dz);
  785. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  786. }
  787. **d = thistime + half_gridsplen;
  788. (*d)++;
  789. **d = 1.0;
  790. (*d)++;
  791. thistime += start_gridwidth;
  792. if(dz->brksize[GRID_SPLEN] > 0) {
  793. read_value_from_brktable(thistime,GRID_SPLEN,dz);
  794. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  795. } else if(*firstpass)
  796. half_gridsplen = dz->param[GRID_SPLEN]/2.0; /* if no brkpnt table, only need to calc on first pass */
  797. *firstpass = 0;
  798. **d = thistime - half_gridsplen;
  799. (*d)++;
  800. **d = 1.0;
  801. (*d)++;
  802. **d = thistime + half_gridsplen;
  803. (*d)++;
  804. **d = 0.0;
  805. (*d)++;
  806. thistime = time + grid_step;
  807. if(dz->brksize[GRID_SPLEN] > 0) {
  808. read_value_from_brktable(thistime,GRID_SPLEN,dz);
  809. half_gridsplen = dz->param[GRID_SPLEN]/2.0;
  810. }
  811. **d = thistime - half_gridsplen;
  812. (*d)++;
  813. **d = 0.0;
  814. (*d)++;
  815. //old_arraysize = *arraysize;
  816. *arraysize += 8;
  817. k = *d - dz->parray[0];
  818. if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],(*arraysize) * sizeof(double)))==NULL) {
  819. sprintf(errstr,"Insufficient memory for grid envelope,\n");
  820. return(MEMORY_ERROR);
  821. }
  822. *d = dz->parray[0] + k;
  823. dz->parray[1] = *d; /* mark end of parray */
  824. }
  825. return(FINISHED);
  826. }
  827. /************************************ DO_GRID_ENVELOPE ********************************/
  828. int do_grid_envelope(dataptr dz)
  829. {
  830. double *ds = dz->parray[0];
  831. int sib, eib; /* startpos-ion-buf, edipos-in-buf */
  832. int style, exit_status, finished= 0;
  833. int startsamp, endsamp, splicepos = 0,last_total_samps_read = 0;
  834. sndseekEx(dz->ifd[0],0,0);
  835. get_nextposition_pair(ds,&startsamp,&endsamp,&style,dz);
  836. sib = startsamp - last_total_samps_read;
  837. eib = endsamp - last_total_samps_read;
  838. if((exit_status = read_samps(dz->sampbuf[0],dz)) < 0)
  839. return(exit_status);
  840. if(dz->ssampsread == 0) {
  841. sprintf(errstr,"No data found in input soundfile\n");
  842. return(GOAL_FAILED);
  843. }
  844. while(ds < dz->parray[1] - 2) {
  845. do {
  846. while(eib < dz->ssampsread) {
  847. do_grid_biz(sib,eib,style,&splicepos,dz);
  848. if((ds += 2) >= dz->parray[1] - 2) {
  849. finished = 1;
  850. break;
  851. }
  852. get_nextposition_pair(ds,&startsamp,&endsamp,&style,dz);
  853. sib = startsamp - last_total_samps_read;
  854. eib = endsamp - last_total_samps_read;
  855. }
  856. if(finished)
  857. break;
  858. do_grid_biz(sib,dz->ssampsread,style,&splicepos,dz);
  859. if(dz->ssampsread > 0) {
  860. if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0)
  861. return(exit_status);
  862. }
  863. last_total_samps_read = dz->total_samps_read;
  864. if((exit_status = read_samps(dz->sampbuf[0],dz)) < 0)
  865. return(exit_status);
  866. if(dz->ssampsread == 0) {
  867. finished = 1;
  868. break;
  869. }
  870. sib = 0;
  871. eib = endsamp - last_total_samps_read;
  872. if(eib == 0) {
  873. if((ds += 2) >= dz->parray[1] - 2) {
  874. finished = 1;
  875. break;
  876. }
  877. get_nextposition_pair(ds,&startsamp,&endsamp,&style,dz);
  878. sib = startsamp - last_total_samps_read;
  879. eib = endsamp - last_total_samps_read;
  880. }
  881. } while(!finished);
  882. if(finished)
  883. break;
  884. }
  885. if(dz->ssampsread > 0) {
  886. if((exit_status = write_samps(dz->sampbuf[0],dz->ssampsread,dz))<0)
  887. return(exit_status);
  888. }
  889. return(FINISHED);
  890. }
  891. /************************************ DO_GRID_BIZ ********************************/
  892. int do_grid_biz(int sib,int eib,int style,int *splicepos,dataptr dz)
  893. {
  894. double splice_incr, splice_val;
  895. int n;
  896. switch(style) {
  897. case(GRID_ZERO): memset((char *)(dz->sampbuf[0] + sib),0,(eib - sib) * sizeof(float)); break;
  898. case(GRID_COPY): break;
  899. case(GRID_UP):
  900. dz->iparam[GRID_SPLEN] = (int)round(dz->param[GRID_SPLEN] * dz->infile->srate) * dz->infile->channels;
  901. splice_incr = 1.0 / (double)dz->iparam[GRID_SPLEN];
  902. splice_val = *splicepos * splice_incr;
  903. for(n = sib; n < eib; n++) {
  904. dz->sampbuf[0][n] = (float)(dz->sampbuf[0][n] * splice_val);
  905. splice_val += splice_incr;
  906. (*splicepos)++;
  907. }
  908. if(*splicepos >= dz->iparam[GRID_SPLEN])
  909. *splicepos = 0;
  910. break;
  911. case(GRID_DOWN):
  912. dz->iparam[GRID_SPLEN] = (int)round(dz->param[GRID_SPLEN] * dz->infile->srate) * dz->infile->channels;
  913. splice_incr = 1.0 / (double)dz->iparam[GRID_SPLEN];
  914. splice_val = 1.0 - (*splicepos * splice_incr);
  915. for(n = sib; n < eib; n++) {
  916. dz->sampbuf[0][n] = (float)(dz->sampbuf[0][n] * splice_val);
  917. splice_val -= splice_incr;
  918. (*splicepos)++;
  919. }
  920. if(*splicepos >= dz->iparam[GRID_SPLEN])
  921. *splicepos = 0;
  922. break;
  923. }
  924. return(FINISHED);
  925. }
  926. /************************************ GET_NEXTPOSITION_PAIR ********************************/
  927. void get_nextposition_pair(double *ds,int *startsamp,int *endsamp,int *style,dataptr dz)
  928. {
  929. double *de = ds+2, startval, endval;
  930. *startsamp = round(*ds * dz->infile->srate) * dz->infile->channels;
  931. *endsamp = round(*de * dz->infile->srate) * dz->infile->channels;
  932. startval = *(ds+1);
  933. endval = *(de+1);
  934. if(flteq(startval,1.0)) {
  935. if(flteq(endval,1.0))
  936. *style = GRID_COPY;
  937. else
  938. *style = GRID_DOWN;
  939. } else {
  940. if(flteq(endval,1.0))
  941. *style = GRID_UP;
  942. else
  943. *style = GRID_ZERO;
  944. }
  945. }