twixt.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695
  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. /*
  23. cmdline...
  24. sfedit twixt mode infile(s) outfile switch-times splicelen (segcnt) [-wweight] [-r]\n\n"
  25. SWITCH_TIMES = special
  26. SPLICETIME in MS = IS_SPLEN
  27. SWITCH_WEIGHT = IS_WEIGHT
  28. FLAG IS_NOTCYCL
  29. TO SPLICE BETWEEN A SERIES OF INFILES USING A LIST OF GIVEN TIMES
  30. */
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <string.h>
  34. #include <math.h>
  35. #include <structures.h>
  36. #include <cdpmain.h>
  37. #include <tkglobals.h>
  38. #include <pnames.h>
  39. #include <edit.h>
  40. #include <processno.h>
  41. #include <modeno.h>
  42. #include <globcon.h>
  43. #include <logic.h>
  44. #include <filetype.h>
  45. #include <mixxcon.h>
  46. #include <flags.h>
  47. #include <speccon.h>
  48. #include <arrays.h>
  49. #include <special.h>
  50. #include <formants.h>
  51. #include <sfsys.h>
  52. #include <osbind.h>
  53. //#ifdef unix
  54. #define round(x) lround((x))
  55. //#endif
  56. static void GetTimes(int fileno,int n,double *lasttime, double *nexttime,dataptr dz);
  57. static int do_output(int fileno,int n,int limit,double lasttime,double nexttime,
  58. double splicestep,int *obufend,int *total_outsamps,dataptr dz);
  59. static int Convert_to_samp(double time,dataptr dz);
  60. static void do_startsplice_in_outbuf(float *buf,double splicestep,dataptr dz);
  61. static void do_startof_endsplice_in_outbuf(float *buf,int splicetodo,double splicestep,dataptr dz);
  62. static int output_samps(int segno,int firsttime,float *outbuf,int outsamps,int *obufend,dataptr dz);
  63. static int flush_outbuf(int segno,int obufend,dataptr dz);
  64. static void randperm(int z,int setlen,dataptr dz);
  65. static void hprefix(int z,int m,int setlen,dataptr dz);
  66. static void hinsert(int z,int m,int t,int setlen,dataptr dz);
  67. static void hshuflup(int z,int k,int setlen,dataptr dz);
  68. static int output_cut_sndfile(dataptr dz);
  69. static int setup_new_outfile(int n,dataptr dz);
  70. static void generate_splicelen(dataptr dz);
  71. static int Getnextfile(int n,int permcnt,dataptr dz);
  72. static void do_endsplice_in_outbuf(float *buf,double splicestep,dataptr dz);
  73. //TW replaced by global F_SECSIZE
  74. //#define FSECSIZE (256) /*RWD*/
  75. /********************************* DO_INTERSPLICE *************************************
  76. *
  77. * THE ALGORITHM
  78. *
  79. * A TWO-STAGE PROCESS:
  80. * 1) We read from an infile into a sector-aligned buffer
  81. * 2) We read from a point in inbuffer (not ness coinciding with its start(which is a sector boundary))
  82. * putting in splice at start of read (and, eventually, splice at end of all reads from this infile)
  83. * 3) WE copy each read to an outbuffer
  84. * 4) Except on very first use, outbuffer always retains a SPLICELEN-segment of data from the previous read
  85. * ready for splice to be made to next file copied into it.
  86. * 5) At start of this copy-to-outbuf we ADD the upsplice-part of new file to end downsplice of previous file
  87. * before proceeding to straightforward copying
  88. */
  89. int do_twixt(dataptr dz)
  90. {
  91. int exit_status, n = 0, limit, fileno;
  92. double lasttime=0.0, nexttime=0.0, splicestep;
  93. int obufend = 0, permcnt = 0, outsamps;
  94. splicestep = 1.0/(SPLICELEN/dz->infile->channels);
  95. if(dz->process != TWIXT || dz->mode != TRUE_EDIT)
  96. permcnt = dz->infilecnt + dz->iparam[IS_WEIGHT] - 1;
  97. if(dz->process == TWIXT && dz->mode == TRUE_EDIT)
  98. limit = dz->itemcnt - 1;
  99. else {
  100. switch(dz->mode) {
  101. case(IN_SEQUENCE):
  102. limit = dz->itemcnt - 1;
  103. break;
  104. default:
  105. limit = dz->iparam[IS_SEGCNT];
  106. break;
  107. }
  108. }
  109. dz->tempsize = (int)limit;
  110. while(n<limit) {
  111. fileno = Getnextfile(n,permcnt,dz);
  112. GetTimes(fileno,n,&lasttime,&nexttime,dz);
  113. if((exit_status = do_output(fileno,n,limit,lasttime,nexttime,splicestep,&obufend,&outsamps,dz))<0)
  114. return(exit_status);
  115. n++;
  116. }
  117. if((exit_status = flush_outbuf(n-1,obufend,dz))<0)
  118. return exit_status;
  119. if(dz->process == TWIXT && dz->mode == TRUE_EDIT) {
  120. if((exit_status = output_cut_sndfile(dz))<0)
  121. return exit_status;
  122. }
  123. return (FINISHED);
  124. }
  125. /********************************* GETTIMES *************************************/
  126. void GetTimes(int arrayno,int n,double *lasttime, double *nexttime,dataptr dz)
  127. {
  128. int k, j, lastperm;
  129. static int init = 1;
  130. int span = dz->itemcnt-1;
  131. if(dz->process == TWIXT) /* only one aray of times, for TWIXT */
  132. arrayno = 0;
  133. if(dz->process == TWIXT && dz->mode == TRUE_EDIT) {
  134. *lasttime = dz->parray[arrayno][n++];
  135. *nexttime = dz->parray[arrayno][n];
  136. } else {
  137. switch(dz->mode) {
  138. case(IN_SEQUENCE):
  139. *lasttime = dz->parray[arrayno][n++];
  140. *nexttime = dz->parray[arrayno][n];
  141. break;
  142. case(RAND_REORDER):
  143. n %= span;
  144. if(n == 0) {
  145. if(init) {
  146. randperm(0,span,dz);
  147. init = 0;
  148. } else {
  149. //TW UPDATE
  150. // lastperm = dz->iparray[arrayno][span-1];
  151. lastperm = dz->iparray[0][span-1];
  152. randperm(0,span,dz);
  153. //TW UPDATE
  154. // if(lastperm == dz->iparray[arrayno][0]) {
  155. // for(j=0;j < span; j++) {
  156. // if(dz->iparray[arrayno][j] != lastperm) {
  157. // dz->iparray[arrayno][0] = dz->iparray[arrayno][j];
  158. // dz->iparray[arrayno][j] = lastperm;
  159. if(lastperm == dz->iparray[0][0]) {
  160. for(j=0;j < span; j++) {
  161. if(dz->iparray[0][j] != lastperm) {
  162. dz->iparray[0][0] = dz->iparray[0][j];
  163. dz->iparray[0][j] = lastperm;
  164. break;
  165. }
  166. }
  167. }
  168. }
  169. }
  170. //TW UPDATE
  171. // k = dz->iparray[arrayno][n];
  172. k = dz->iparray[0][n];
  173. *lasttime = dz->parray[arrayno][k++];
  174. *nexttime = dz->parray[arrayno][k];
  175. break;
  176. case(RAND_SEQUENCE):
  177. k = (int)floor(drand48() * span);
  178. *lasttime = dz->parray[arrayno][k++];
  179. *nexttime = dz->parray[arrayno][k];
  180. break;
  181. }
  182. }
  183. }
  184. /********************************* DO_OUTPUT *************************************/
  185. /*RWD 6:2001: NB permcnt,n unused */
  186. int do_output(int fileno,int n,int limit,double lasttime,double nexttime,double splicestep,
  187. int *obufend,int *total_outsamps,dataptr dz)
  188. {
  189. int exit_status;
  190. static int init;
  191. int lastsamp = Convert_to_samp(lasttime,dz);
  192. int nextsamp = Convert_to_samp(nexttime,dz);
  193. int firsttime = 1;
  194. int remaining_samps_to_write, startbuf, offset, rotate, max_possible_outsamps, outsamps, startsplice;
  195. float *inbuf, *outbuf;
  196. if(nextsamp - lastsamp < SPLICELEN) /* Possible for final segment */
  197. return(FINISHED);
  198. lastsamp = max(0,lastsamp - SPLICELEN); /* adjust so upsplice starts before start of segment */
  199. remaining_samps_to_write = nextsamp - lastsamp;
  200. *total_outsamps = remaining_samps_to_write;
  201. startbuf = (lastsamp/dz->iparam[IS_SHSECSIZE]) * dz->iparam[IS_SHSECSIZE];
  202. offset = lastsamp - startbuf;
  203. rotate = dz->iparam[IS_SHSECSIZE] - offset;
  204. /*
  205. * x = offset, start of outbuf
  206. * y = SECTOR-minus-x left at end
  207. *
  208. * b_________________________________c
  209. * x | |y
  210. * |_____________INBUF positioned ___________|
  211. * so y can be copied to its start
  212. *
  213. * 1st time, output from b to c = sampbuflen - dz->iparam[IS_SHSECSIZE]
  214. * then copy 'y' to before start of inbuf
  215. * Other reads, output from a to c. = sampbuflen
  216. * then copy 'y' to before start of inbuf
  217. *
  218. * a_____b_________________________________c
  219. *|y| x |
  220. *|_____sampbuf = standardsize + SECTOR_________|
  221. *
  222. */
  223. inbuf = dz->sampbuf[0] + (dz->iparam[IS_SHSECSIZE] - offset);
  224. outbuf = inbuf + offset;
  225. max_possible_outsamps = dz->buflen - dz->iparam[IS_SHSECSIZE];
  226. sndseekEx(dz->ifd[fileno],startbuf,0);
  227. dz->total_samps_read = startbuf;
  228. do {
  229. if(n!=0 && (dz->process == TWIXT) && (dz->mode == TRUE_EDIT) && firsttime) {
  230. if((exit_status = setup_new_outfile(n,dz))<0)
  231. return(exit_status);
  232. }
  233. if((dz->ssampsread = fgetfbufEx(inbuf, dz->buflen,dz->ifd[fileno],0)) < 0) {
  234. sprintf(errstr,"Can't read samples from input soundfile.\n");
  235. return(SYSTEM_ERROR);
  236. }
  237. if(dz->ssampsread == 0)
  238. break;
  239. if(firsttime && !init)
  240. do_startsplice_in_outbuf(outbuf,splicestep,dz);
  241. else
  242. init = 0;
  243. if(max_possible_outsamps >= remaining_samps_to_write) {
  244. outsamps = remaining_samps_to_write;
  245. do_endsplice_in_outbuf(outbuf + outsamps - SPLICELEN,splicestep,dz);
  246. } else {
  247. outsamps = max_possible_outsamps;
  248. if ((startsplice = remaining_samps_to_write - SPLICELEN) < outsamps)
  249. do_startof_endsplice_in_outbuf(outbuf + startsplice,outsamps - startsplice,splicestep,dz);
  250. }
  251. output_samps(n,firsttime,outbuf,outsamps,obufend,dz);
  252. remaining_samps_to_write -= outsamps;
  253. memcpy((char *)dz->sampbuf[0],(char *)(outbuf + outsamps),rotate * sizeof(float));
  254. outbuf = dz->sampbuf[0]; /* after first output */
  255. max_possible_outsamps = dz->buflen;
  256. firsttime = 0;
  257. } while(remaining_samps_to_write > 0);
  258. if((dz->process == TWIXT) && (dz->mode == TRUE_EDIT) && (n != limit - 1)) {
  259. if((exit_status = flush_outbuf(n,*obufend,dz))<0)
  260. return exit_status;
  261. *obufend = 0;
  262. return output_cut_sndfile(dz);
  263. }
  264. return(FINISHED);
  265. }
  266. /********************************* CONVERT_TO_SAMP *************************************/
  267. int Convert_to_samp(double time,dataptr dz)
  268. {
  269. int sampcnt = (int)round(time * dz->infile->srate);
  270. sampcnt *= dz->infile->channels;
  271. return(sampcnt);
  272. }
  273. /********************************* DO_STARTSPLICE_IN_OUTBUF *************************************/
  274. void do_startsplice_in_outbuf(float *buf,double splicestep,dataptr dz)
  275. {
  276. int chans = dz->infile->channels;
  277. double q, mult = 0.0;
  278. int k, n = 0;
  279. while(n < SPLICELEN) {
  280. mult += splicestep;
  281. for(k = 0; k < chans; k++) {
  282. q = *buf * mult;
  283. *buf++ = (float) /*round*/(q);
  284. n++;
  285. }
  286. }
  287. }
  288. /********************************* DO_ENDSPLICE_IN_OUTBUF *************************************/
  289. void do_endsplice_in_outbuf(float *buf,double splicestep,dataptr dz)
  290. {
  291. int chans = dz->infile->channels;
  292. double q, mult = 1.0;
  293. int k, n = 0;
  294. while(n < SPLICELEN) {
  295. mult -= splicestep;
  296. for(k = 0; k < chans; k++) {
  297. q = *buf * mult;
  298. *buf++ = (float) /*round*/(q);
  299. n++;
  300. }
  301. }
  302. }
  303. /********************************* DO_STARTOF_ENDSPLICE_IN_OUTBUF *************************************/
  304. void do_startof_endsplice_in_outbuf(float *buf,int splicetodo,double splicestep,dataptr dz)
  305. {
  306. int chans = dz->infile->channels;
  307. double q, mult = 1.0;
  308. int k, n = 0;
  309. while(n < splicetodo) {
  310. mult -= splicestep;
  311. for(k = 0; k < chans; k++) {
  312. q = *buf * mult;
  313. *buf++ = (float) /*round*/(q);
  314. n++;
  315. }
  316. }
  317. }
  318. /********************************* OUTPUT_SAMPS *************************************/
  319. int output_samps(int segno,int firsttime,float *outbuf,int outsamps,int *obufend,dataptr dz)
  320. {
  321. /* true length of buf = buflen + SPLICELEN */
  322. int exit_status;
  323. int n, samps_to_copy, xs;
  324. int samps_to_write = dz->buflen ;
  325. int space_in_outbuf = dz->buflen + SPLICELEN - *obufend;
  326. float *thisbuf = dz->sampbuf[1] + *obufend;
  327. static int ob_firsttime = 1;
  328. if(ob_firsttime) {
  329. memcpy((char *)thisbuf,(char *)outbuf,outsamps * sizeof(float));
  330. *obufend = outsamps;
  331. ob_firsttime = 0;
  332. } else {
  333. if(firsttime && (dz->process != TWIXT || dz->mode != TRUE_EDIT)) {
  334. thisbuf -= SPLICELEN;
  335. for(n=0; n < SPLICELEN; n++)
  336. thisbuf[n] = (float)(thisbuf[n] + outbuf[n]);
  337. thisbuf += SPLICELEN;
  338. outbuf += SPLICELEN;
  339. samps_to_copy = outsamps - SPLICELEN;
  340. } else
  341. samps_to_copy = outsamps;
  342. if((xs = samps_to_copy - space_in_outbuf) < 0) {
  343. memcpy((char *)thisbuf,(char *)outbuf,samps_to_copy * sizeof(float));
  344. *obufend += samps_to_copy;
  345. } else {
  346. memcpy((char *)thisbuf,(char *)outbuf,space_in_outbuf * sizeof(float));
  347. samps_to_write = dz->buflen;
  348. superzargo = segno + 1;
  349. if((exit_status = write_samps(dz->sampbuf[1],samps_to_write,dz))<0)
  350. return(exit_status);
  351. thisbuf = dz->sampbuf[1];
  352. memcpy((char *)thisbuf,(char *)(thisbuf + dz->buflen),SPLICELEN * sizeof(float));
  353. memset((char *)(thisbuf+SPLICELEN),0,samps_to_write);
  354. *obufend = SPLICELEN;
  355. if(xs > 0) {
  356. thisbuf += *obufend;
  357. outbuf += space_in_outbuf;
  358. memcpy((char *)thisbuf,(char *)outbuf,xs * sizeof(float));
  359. *obufend += xs;
  360. }
  361. }
  362. }
  363. return(FINISHED);
  364. }
  365. /********************************* FLUSH_OUTBUF *************************************/
  366. int flush_outbuf(int segno,int obufend,dataptr dz)
  367. {
  368. int exit_status;
  369. int samps_to_write = obufend;
  370. superzargo = segno+1;
  371. if(samps_to_write > 0) {
  372. if((exit_status = write_samps(dz->sampbuf[1],samps_to_write,dz))<0)
  373. return(exit_status);
  374. }
  375. return(FINISHED);
  376. }
  377. /********************************* RANDPERM *************************************/
  378. void randperm(int z,int setlen,dataptr dz)
  379. {
  380. int n, t;
  381. for(n=0;n<setlen;n++) {
  382. t = (int)floor(drand48() * (n+1));
  383. if(t>=n)
  384. hprefix(z,n,setlen,dz);
  385. else
  386. hinsert(z,n,t,setlen,dz);
  387. }
  388. }
  389. /***************************** HINSERT **********************************
  390. *
  391. * Insert the value m AFTER the T-th element in iparray[].
  392. */
  393. void hinsert(int z,int m,int t,int setlen,dataptr dz)
  394. {
  395. hshuflup(z,t+1,setlen,dz);
  396. dz->iparray[z][t+1] = m;
  397. }
  398. /***************************** HPREFIX ************************************
  399. *
  400. * Insert the value m at start of the permutation iparray[].
  401. */
  402. void hprefix(int z,int m,int setlen,dataptr dz)
  403. {
  404. hshuflup(z,0,setlen,dz);
  405. dz->iparray[z][0] = m;
  406. }
  407. /****************************** HSHUFLUP ***********************************
  408. *
  409. * move set members in iparray[] upwards, starting from element k.
  410. */
  411. void hshuflup(int z,int k,int setlen,dataptr dz)
  412. {
  413. int n, *i;
  414. int y = setlen - 1;
  415. i = (dz->iparray[z]+y);
  416. for(n = y;n > k;n--) {
  417. *i = *(i-1);
  418. i--;
  419. }
  420. }
  421. /********************************** OUTPUT_CUT_SNDFILE ********************************/
  422. int output_cut_sndfile(dataptr dz)
  423. {
  424. int exit_status;
  425. char filename[64];
  426. if((exit_status = headwrite(dz->ofd,dz))<0)
  427. return(exit_status);
  428. dz->process_type = OTHER_PROCESS; /* stop process trying to deal with outfile later */
  429. dz->outfiletype = NO_OUTPUTFILE; /* stop process trying to deal with outfile later */
  430. if(sndcloseEx(dz->ofd) < 0) {
  431. fprintf(stdout,"WARNING: Can't close output soundfile %s\n",filename);
  432. fflush(stdout);
  433. }
  434. dz->ofd = -1;
  435. return(FINISHED);
  436. }
  437. /********************************** SETUP_NEW_OUTFILE ********************************/
  438. int setup_new_outfile(int n,dataptr dz)
  439. {
  440. int exit_status;
  441. char filename[64];
  442. strcpy(filename,dz->wordstor[0]);
  443. insert_new_number_at_filename_end(filename,n,1);
  444. dz->process_type = UNEQUAL_SNDFILE; /* allow sndfile to be created */
  445. dz->outfiletype = SNDFILE_OUT; /* allows header to be written */
  446. if((exit_status = create_sized_outfile(filename,dz))<0) {
  447. fprintf(stdout, "WARNING: Cannot create Soundfile %s : %s\n", filename, rsferrstr);
  448. fflush(stdout);
  449. dz->process_type = OTHER_PROCESS;
  450. dz->outfiletype = NO_OUTPUTFILE; /* stop process trying to deal with outfile later */
  451. dz->ofd = -1;
  452. return(GOAL_FAILED);
  453. }
  454. return(FINISHED);
  455. }
  456. /*************************** CREATE_TWIXT_BUFFERS **************************/
  457. int create_twixt_buffers(dataptr dz)
  458. {
  459. int bigsize;
  460. size_t bigbufsize;
  461. int framesize = F_SECSIZE * dz->infile->channels;
  462. if(dz->sbufptr == 0 || dz->sampbuf==0) {
  463. sprintf(errstr,"buffer pointers not allocated: create_sndbufs()\n");
  464. return(PROGRAM_ERROR);
  465. }
  466. bigbufsize = (size_t) Malloc(-1);
  467. bigbufsize -= (SPLICELEN + F_SECSIZE) * sizeof(float);
  468. bigbufsize /= dz->bufcnt;
  469. dz->buflen = (int)(bigbufsize/sizeof(float));
  470. dz->buflen = (dz->buflen / framesize) * framesize;
  471. if(dz->buflen <= 0)
  472. dz->buflen = framesize;
  473. bigsize = (dz->buflen * dz->bufcnt) + SPLICELEN + F_SECSIZE;
  474. if((dz->bigbuf = (float *)malloc(bigsize * sizeof(float))) == NULL) {
  475. sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
  476. return(PROGRAM_ERROR);
  477. }
  478. dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf;
  479. dz->sbufptr[1] = dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen + dz->iparam[IS_SHSECSIZE];
  480. dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen + SPLICELEN;
  481. memset((char *)dz->bigbuf,0,bigsize * sizeof(float));
  482. return(FINISHED);
  483. }
  484. /*************************** TWIXT_PREPROCESS **************************/
  485. int twixt_preprocess(dataptr dz)
  486. {
  487. double *p, last, next = 0.0;
  488. int n;
  489. int minsamps = dz->insams[0];
  490. for(n = 1; n<dz->infilecnt;n++)
  491. minsamps = min(minsamps,dz->insams[n]);
  492. dz->duration = (double)(minsamps/dz->infile->channels)/(double)dz->infile->srate;
  493. if(dz->mode != TRUE_EDIT) {
  494. if((dz->iparray[1] = (int *)malloc((dz->infilecnt + dz->iparam[IS_WEIGHT] - 1) * sizeof(int)))==NULL) {
  495. sprintf(errstr,"INSUFFICIENT MEMORY to allocate file permutation store.\n");
  496. return(MEMORY_ERROR);
  497. }
  498. }
  499. generate_splicelen(dz);
  500. p = dz->parray[0];
  501. if((last = *p++) > dz->duration) {
  502. sprintf(errstr,"First time in datafile is beyond end of shortest input soundfile (%lf)\n",dz->duration);
  503. return(DATA_ERROR);
  504. }
  505. n = 2;
  506. while(n <= dz->itemcnt) {
  507. if((next = *p++) > dz->duration) {
  508. sprintf(errstr,"Times beyond number %d ( = %lf) in datafile are beyond end of shortest input soundfile (%lf)\n",
  509. n-1,last,dz->duration);
  510. return(DATA_ERROR);
  511. }
  512. if(next - last <= dz->param[IS_SPLICETIME]) {
  513. sprintf(errstr,"distant between splicepoints %d & %d (%lf) less than time needed for splices (%lf)\n",
  514. n,n-1,next-last,dz->param[IS_SPLICETIME]);
  515. return(DATA_ERROR);
  516. }
  517. last = next;
  518. n++;
  519. }
  520. if(dz->duration - next > dz->param[IS_SPLICETIME]) {
  521. if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],(dz->itemcnt+1) * sizeof(double)))==NULL) {
  522. sprintf(errstr,"Insufficient memory to store time-switch data.\n");
  523. return(MEMORY_ERROR);
  524. }
  525. dz->parray[0][dz->itemcnt] = dz->duration;
  526. dz->itemcnt++;
  527. }
  528. return(FINISHED);
  529. }
  530. /*************************** SPHINX_PREPROCESS **************************/
  531. int sphinx_preprocess(dataptr dz)
  532. {
  533. double *p, last, next;
  534. int n, k;
  535. if((dz->iparray[1] = (int *)malloc((dz->infilecnt + dz->iparam[IS_WEIGHT] - 1) * sizeof(int)))==NULL) {
  536. sprintf(errstr,"INSUFFICIENT MEMORY to allocate file permutation store.\n");
  537. return(MEMORY_ERROR);
  538. }
  539. generate_splicelen(dz);
  540. for(k=0;k<dz->array_cnt;k++) {
  541. p = dz->parray[k];
  542. last = *p++;
  543. n = 2;
  544. while(n <= dz->itemcnt) {
  545. next = *p++;
  546. if(next - last <= dz->param[IS_SPLICETIME]) {
  547. sprintf(errstr,"distant between splicepoints %d & %d (%lf) less than time needed for splices (%lf)\n",
  548. n,n-1,next-last,dz->param[IS_SPLICETIME]);
  549. return(DATA_ERROR);
  550. }
  551. last = next;
  552. n++;
  553. }
  554. }
  555. return(FINISHED);
  556. }
  557. /*************************** GENERATE_SPLICELEN **************************/
  558. void generate_splicelen(dataptr dz)
  559. {
  560. double splicetime;
  561. int j;
  562. dz->iparam[IS_SHSECSIZE] = F_SECSIZE;
  563. splicetime = dz->param[IS_SPLEN] * MS_TO_SECS;
  564. j = round(splicetime * dz->infile->srate);
  565. j *= dz->infile->channels;
  566. SPLICELEN = j;
  567. dz->param[IS_SPLICETIME] = (double)(SPLICELEN/dz->infile->channels)/(double)dz->infile->srate;
  568. }
  569. /*************************** GETNEXTFILE **************************/
  570. int Getnextfile(int n,int permcnt,dataptr dz)
  571. {
  572. int lastperm, j, k;
  573. static int init = 1;
  574. if(dz->process == TWIXT && dz->mode == TRUE_EDIT)
  575. return 0;
  576. n %= permcnt;
  577. if((permcnt == dz->infilecnt) && !dz->vflag[IS_NOTCYCL]) /* with no weighting, and cyclic files specified */
  578. return n;
  579. if(n == 0) {
  580. if(init) {
  581. randperm(1,permcnt,dz);
  582. for(j=0;j < permcnt;j++) {
  583. if(dz->iparray[1][j] >= dz->infilecnt) /* substitute file1 for extra spaces in perm */
  584. dz->iparray[1][j] = 0;
  585. }
  586. if(dz->iparray[1][0] != 0) {
  587. for(j=1;j < permcnt;j++) { /* Force first file to be first !! */
  588. if(dz->iparray[1][j] == 0) {
  589. dz->iparray[1][j] = dz->iparray[1][0];
  590. dz->iparray[1][0] = 0;
  591. break;
  592. }
  593. }
  594. }
  595. if(!dz->vflag[IS_NOTCYCL]) {
  596. k = 1;
  597. for(j=1;j < permcnt;j++) { /* Force un-first files to be in order */
  598. if(dz->iparray[1][j] != 0)
  599. dz->iparray[1][j] = k++;
  600. }
  601. }
  602. init = 0;
  603. } else {
  604. lastperm = dz->iparray[1][permcnt - 1];
  605. randperm(1,permcnt,dz);
  606. for(j=0;j < permcnt;j++) { /* substitute file1 for extra spaces in perm */
  607. if(dz->iparray[1][j] >= dz->infilecnt)
  608. dz->iparray[1][j] = 0;
  609. } /* avoid repets at perm boundaries */
  610. if((dz->iparray[1][0] == lastperm) && ((lastperm != 0) || (dz->iparam[IS_WEIGHT] == 1))) {
  611. for(j=1;j < permcnt;j++) {
  612. if(dz->iparray[1][j] != lastperm) {
  613. dz->iparray[1][0] = dz->iparray[1][j];
  614. dz->iparray[1][j] = lastperm;
  615. break;
  616. }
  617. }
  618. }
  619. if(!dz->vflag[IS_NOTCYCL]) {
  620. k = 1;
  621. for(j=1;j < permcnt;j++) { /* Force un-first files to be in order */
  622. if(dz->iparray[1][j] != 0)
  623. dz->iparray[1][j] = k++;
  624. }
  625. }
  626. }
  627. }
  628. return dz->iparray[1][n];
  629. }