radical.c 71 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019
  1. /*
  2. * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. /* floatsam version */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <memory.h>
  25. #include <string.h>
  26. #include <structures.h>
  27. #include <tkglobals.h>
  28. #include <globcon.h>
  29. #include <arrays.h>
  30. #include <cdpmain.h>
  31. #include <modify.h>
  32. #include <modeno.h>
  33. //TW UPDATES
  34. #include <arrays.h>
  35. #include <flags.h>
  36. #include <sfsys.h>
  37. #include <osbind.h>
  38. //#ifdef unix
  39. #define round(x) lround((x))
  40. //#endif
  41. #ifndef HUGE
  42. #define HUGE 3.40282347e+38F
  43. #endif
  44. //extern int snd_makepath(char path[],const char *sfname);
  45. extern char *get_other_filename_x(char *filename,char c);
  46. #define SCRUB_FORWARDS (TRUE)
  47. #define SCRUB_BACKWARDS (FALSE)
  48. #define SCRUB_SAFE (.66)
  49. static void reverse_the_buffer(float *ibuf,int chans,long ssampsread);
  50. static int do_lowbit(float *maxsamp,float *postmaxsamp,dataptr dz);
  51. static int do_lowbit2(dataptr dz);
  52. static int shred(int current_buf,int work_len,dataptr dz);
  53. static int get_basis_lengths(int *worklen,dataptr dz);
  54. static void normal_scat(dataptr dz);
  55. static void heavy_scat(dataptr dz);
  56. static void permute_chunks(dataptr dz);
  57. static void insert(int n,int t,dataptr dz);
  58. static void prefix(int n,dataptr dz);
  59. static void shuflup(int k,dataptr dz);
  60. static void do_startsplice(float *i,float *j,dataptr dz);
  61. static void do_endsplice(float *i,float *j,dataptr dz);
  62. static void do_bufend_splices(int current_buf,dataptr dz);
  63. static void ptr_sort(int end,dataptr dz);
  64. static int check_for_too_small_buf(dataptr dz);
  65. static int create_sintable(dataptr dz);
  66. static double get_skew(void);
  67. static void get_speed(double *lospeed,double *speedrang,dataptr dz);
  68. static void get_end(int *direction,int *here,dataptr dz);
  69. static int gen_readtab(double skew,double lospeed,double speedrange,int scrublen_in_src,dataptr dz);
  70. static int scrub(int *hhere,int *tthere,int direction,int effective_tablen,dataptr dz);
  71. static int read_samps_for_scrub(int bufno,dataptr dz);
  72. static double read_rmod_tab(double dtabindex,dataptr dz);
  73. //TW UPDATES (converted to flotsams)
  74. static int get_obuf_sampoffset(int n,dataptr dz);
  75. static int transpos_and_add_to_obuf(int n,int *obufpos,double *inbufpos,float *lastival,int chans,dataptr dz);
  76. /******************************* CREATE_REVERSING_BUFFERS *******************************/
  77. int create_reversing_buffers(dataptr dz)
  78. {
  79. //TW BIG SIMPLIFICATION as buffer sector-alignment abolished
  80. size_t bigbufsize;
  81. bigbufsize = (size_t) Malloc(-1);
  82. dz->buflen = (int)(bigbufsize / sizeof(float));
  83. dz->buflen = (dz->buflen / dz->infile->channels) * dz->infile->channels;
  84. dz->iparam[REV_BUFCNT] = dz->insams[0]/dz->buflen;
  85. if(dz->iparam[REV_BUFCNT] > 0)
  86. dz->iparam[REV_RSAMPS] = dz->insams[0] - (dz->iparam[REV_BUFCNT] * dz->buflen);
  87. if((dz->bigbuf = (float *)malloc(dz->buflen * sizeof(float)))==NULL) {
  88. sprintf(errstr,"INSUFFICIENT MEMORY for sound buffers.\n");
  89. return(MEMORY_ERROR);
  90. }
  91. dz->sampbuf[0] = dz->bigbuf;
  92. return FINISHED;
  93. }
  94. /******************************* DO_REVERSING *******************************/
  95. int do_reversing(dataptr dz)
  96. {
  97. //TW BIG SIMPLIFICATION as buffer sector-alignment abolished
  98. int exit_status;
  99. float *buf = dz->sampbuf[0];
  100. int chans = dz->infile->channels;
  101. int nbuffs = dz->iparam[REV_BUFCNT];
  102. int thisbufsamps;
  103. if(nbuffs <=0) {
  104. if((exit_status = read_samps(buf,dz)) < 0) {
  105. sprintf(errstr,"Failed (1) to read input file.\n");
  106. return(PROGRAM_ERROR);
  107. }
  108. if(dz->ssampsread != dz->insams[0]) {
  109. sprintf(errstr,"Bad accounting.\n");
  110. return(PROGRAM_ERROR);
  111. }
  112. reverse_the_buffer(buf,chans,dz->ssampsread);
  113. if(dz->ssampsread > 0) {
  114. if((exit_status = write_samps(buf,dz->ssampsread,dz)) < 0) {
  115. sprintf(errstr,"Failed (1) to write to output file.");
  116. return(PROGRAM_ERROR);
  117. }
  118. }
  119. } else {
  120. thisbufsamps = dz->insams[0] - dz->iparam[REV_RSAMPS];
  121. if((sndseekEx(dz->ifd[0], thisbufsamps, 0)) < 0) {
  122. sprintf(errstr,"Reverse: failed to seek to point in file\n");
  123. return(SYSTEM_ERROR);
  124. }
  125. if((thisbufsamps -= dz->buflen)<0) { /* ready for next iteration */
  126. sprintf(errstr,"Bad accounting 1.\n");
  127. return(PROGRAM_ERROR);
  128. }
  129. if((exit_status = read_samps(buf,dz)) < 0) {
  130. sprintf(errstr,"Failed (1a) to read input file\n");
  131. return(PROGRAM_ERROR);
  132. }
  133. if(dz->ssampsread != dz->iparam[REV_RSAMPS]) {
  134. sprintf(errstr,"Bad accounting 2.\n");
  135. return(PROGRAM_ERROR);
  136. }
  137. reverse_the_buffer(buf,chans,dz->ssampsread);
  138. if(dz->ssampsread > 0) {
  139. if((write_samps(buf, dz->ssampsread,dz)) < 0) { /* writes (truncated number of) whole sector */
  140. sprintf(errstr,"Failed (1a) to write to output file");
  141. return(SYSTEM_ERROR);
  142. }
  143. }
  144. while(nbuffs>0) {
  145. if((sndseekEx(dz->ifd[0], thisbufsamps, 0)) < 0) {
  146. sprintf(errstr,"Reverse: failed to seek to point in file.\n");
  147. return(SYSTEM_ERROR);
  148. }
  149. if((exit_status = read_samps(buf,dz)) < 0) {
  150. sprintf(errstr,"Failed (1b) to read input file\n");
  151. return(PROGRAM_ERROR);
  152. }
  153. if(dz->ssampsread != dz->buflen) {
  154. sprintf(errstr,"Bad accounting 3.\n");
  155. return(PROGRAM_ERROR);
  156. }
  157. nbuffs--;
  158. if(nbuffs>0 && (thisbufsamps -= dz->buflen)<0) { /* ready for next iteration */
  159. sprintf(errstr,"Bad accounting 4.\n");
  160. return(PROGRAM_ERROR);
  161. }
  162. reverse_the_buffer(buf,chans,dz->ssampsread);
  163. if(dz->ssampsread > 0) {
  164. if((exit_status = write_exact_samps(buf,dz->ssampsread,dz)) < 0) {
  165. sprintf(errstr,"Failed (1b) to write to output file");
  166. return(PROGRAM_ERROR);
  167. }
  168. }
  169. }
  170. }
  171. return(FINISHED);
  172. }
  173. /******************************* REVERSE_THE_BUFFER *******************************/
  174. void reverse_the_buffer(float *ibuf,int chans,long ssampsread)
  175. {
  176. int half_ssampsread = ((ssampsread/chans)/2) * chans;
  177. int n, m, k;
  178. float temp;
  179. for(n = 0,m = ssampsread-chans;n< half_ssampsread;n+=chans,m-=chans) {
  180. for(k=0;k<chans;k++) {
  181. temp = ibuf[n+k];
  182. ibuf[n+k] = ibuf[m+k];
  183. ibuf[m+k] = temp;
  184. }
  185. }
  186. }
  187. /***************************** LOBIT_PCONSISTENCY *************************/
  188. int lobit_pconsistency(dataptr dz)
  189. {
  190. int garf = 1;
  191. int m;
  192. SFPROPS props = {0};
  193. if(!snd_headread(dz->ifd[0],&props)) {
  194. fprintf(stdout,"Failure to read sample size\n");
  195. fflush(stdout);
  196. return(DATA_ERROR);
  197. }
  198. //TW ADDED
  199. dz->iparam[LOBIT_BRES_SHIFT] = 0;
  200. if(dz->iparam[LOBIT_BRES]!=MAX_BIT_DIV) {
  201. dz->iparam[LOBIT_BRES] = MAX_BIT_DIV - dz->iparam[LOBIT_BRES];
  202. //TW DISCOVERED ERROR
  203. // garf = 1;
  204. garf = 2;
  205. for(m=1;m<dz->iparam[LOBIT_BRES];m++)
  206. garf *= 2;
  207. dz->iparam[LOBIT_BRES] = garf;
  208. //TW SIMPLIFIED, removed shift arithmetic
  209. }
  210. //TW ADDED non-16-bit cases
  211. switch(props.samptype) {
  212. case(0): /* SHORT8 */
  213. case(7): /* INT_MASKED */
  214. sprintf(errstr,"Process does not work with 8-bit files.\n");
  215. return(DATA_ERROR);
  216. case(1): /* SHORT16 */ break;
  217. case(2): /* FLOAT32 */
  218. case(3): /* INT_32 */ dz->iparam[LOBIT_BRES] *= (256 * 256); break;
  219. case(4): /* INT2424 */
  220. case(5): /* INT2432 */ dz->iparam[LOBIT_BRES] *= 256; break;
  221. case(6): /* INT2024 */ dz->iparam[LOBIT_BRES] *= 16; break;
  222. default:
  223. sprintf(errstr,"Unknown sample type.\n");
  224. return(DATA_ERROR);
  225. }
  226. //TW SIMPLIFIED, removed shift arithmetic for the time averaging
  227. return(FINISHED);
  228. }
  229. /****************************** LOBIT_PROCESS *************************/
  230. int lobit_process(dataptr dz)
  231. {
  232. int exit_status;
  233. float *buffer = dz->sampbuf[0];
  234. float maxsamp = 0.0, postmaxsamp = 0.0;
  235. display_virtual_time(0L,dz);
  236. if(dz->mode == MOD_LOBIT)
  237. dz->buflen = (dz->buflen / (dz->iparam[LOBIT_TSCAN] * dz->infile->channels)) * dz->iparam[LOBIT_TSCAN] * dz->infile->channels;
  238. while(dz->samps_left != 0) {
  239. if((exit_status = read_samps(buffer,dz))<0)
  240. return(exit_status);
  241. switch(dz->mode) {
  242. case(MOD_LOBIT):
  243. if((exit_status = do_lowbit(&maxsamp,&postmaxsamp,dz))<0)
  244. return(exit_status);
  245. break;
  246. case(MOD_LOBIT2):
  247. if((exit_status = do_lowbit2(dz))<0)
  248. return(exit_status);
  249. break;
  250. }
  251. if(dz->ssampsread > 0) {
  252. if((exit_status = write_exact_samps(buffer,dz->ssampsread,dz))<0)
  253. return(exit_status);
  254. }
  255. }
  256. return(FINISHED);
  257. }
  258. /**************************** DO_LOWBIT ***************************/
  259. int do_lowbit(float *maxsamp,float *postmaxsamp,dataptr dz)
  260. {
  261. register int i, j;
  262. double x, maxsampval;
  263. int k, todo_samples;
  264. int n;
  265. //TW MODIFIED FOR floats and non-16-bit sndfile formats
  266. float *buffer = dz->sampbuf[0];
  267. int tscan = dz->iparam[LOBIT_TSCAN];
  268. int bres = dz->iparam[LOBIT_BRES];
  269. int chans = dz->infile->channels;
  270. SFPROPS props = {0};
  271. if(!snd_headread(dz->ifd[0],&props)) {
  272. fprintf(stdout,"Failure to read sample size\n");
  273. fflush(stdout);
  274. return(DATA_ERROR);
  275. }
  276. switch(props.samptype) {
  277. case(1): /* SHORT16 */ maxsampval = MAXSAMP; break;
  278. case(2): /* FLOAT32 */
  279. case(3): /* INT_32 */ maxsampval = 2147483647.0; break;
  280. case(4): /* INT2424 */
  281. case(5): /* INT2432 */ maxsampval = 8388607.0; break;
  282. case(6): /* INT2024 */ maxsampval = 524287.0; break;
  283. /*RWD April 2004: need a default case; may add new formats one day! */
  284. /* OR: make one of the above cases the default... */
  285. default:
  286. fprintf(stdout,"Unsupported sample type\n");
  287. fflush(stdout);
  288. return(DATA_ERROR);
  289. /* other cases rejected earlier */
  290. }
  291. if(tscan!=1) {
  292. if((todo_samples = (dz->ssampsread/(tscan * chans)) * tscan * chans) != dz->ssampsread) {
  293. for(i = todo_samples;i<dz->ssampsread;i++)
  294. buffer[i] = 0.0f;
  295. dz->ssampsread = todo_samples;
  296. }
  297. }
  298. //TW MODIFIED to include non-16-bit cases, & files that are not mono
  299. for(i = 0; i < dz->ssampsread; i += (tscan * chans)) {
  300. for(n=0;n < chans; n++) {
  301. x = 0.0;
  302. k = i + n + (tscan * chans);
  303. for(j = i+n;j < k; j+= chans) {
  304. *maxsamp = (float) max(*maxsamp,fabs(buffer[j]));
  305. x += buffer[j];
  306. }
  307. x /= tscan; /* Take a time average */
  308. x *= maxsampval; /* convert to 'integer' range */
  309. x /= bres;
  310. x = (double)round(x); /* do a rounding mod bres */
  311. x *= bres;
  312. x /= maxsampval;
  313. x = min(x,1.0);
  314. x = max(x,-1.0);
  315. k = min(k,dz->ssampsread);
  316. for(j = i+n;j < k; j+= chans) {
  317. buffer[j] = (float)x; /* reconvert to float range */
  318. *postmaxsamp = (float) max(*postmaxsamp,fabs(buffer[j]));
  319. }
  320. }
  321. }
  322. return(FINISHED);
  323. }
  324. /**************************** DO_LOWBIT2 ***************************/
  325. int do_lowbit2(dataptr dz)
  326. {
  327. int n;
  328. //TW MODIFIED FOR floats and non-16-bit sndfile formats
  329. float *buffer = dz->sampbuf[0];
  330. double samp;
  331. int srcbits = 16; // We assume src is quasi-16bit
  332. int nbits = dz->iparam[LOBIT_BRES];
  333. int rescalebits = srcbits - nbits;
  334. double rescalefac = pow(2.0,rescalebits);
  335. for(n = 0; n < dz->ssampsread; n++) {
  336. samp = buffer[n] * 32767.0; // prescale to 16-bit range
  337. if(samp <= -32767.0)
  338. samp = -32767.0; // keep within range
  339. // do mid-rise quantisation
  340. samp /= rescalefac;
  341. samp = round(samp+0.5) - 0.5; // round to a multiple of 0.5
  342. samp *= rescalefac;
  343. // rescale back to float 0-1 representation
  344. buffer[n] = (float)(samp/32768.0);
  345. }
  346. return FINISHED;
  347. }
  348. /***************************** SHRED_PCONSISTENCY *************************/
  349. int shred_pconsistency(dataptr dz)
  350. {
  351. int chans = dz->infile->channels;
  352. double duration = (double)(dz->insams[0]/chans)/(double)dz->infile->srate;
  353. initrand48();
  354. dz->iparam[SHR_CHCNT] = round(duration/dz->param[SHRED_CHLEN]);
  355. if(dz->param[SHRED_SCAT] > (double)dz->iparam[SHR_CHCNT]) {
  356. sprintf(errstr,"Scatter value cannot be greater than infileduration/chunklength.\n");
  357. return(DATA_ERROR);
  358. }
  359. if(dz->param[SHRED_SCAT] > 1.0)
  360. dz->iparam[SHRED_SCAT] = round(dz->param[SHRED_SCAT]);
  361. else
  362. dz->iparam[SHRED_SCAT] = 0;
  363. /* setup splice params */
  364. dz->iparam[SHRED_SPLEN] = SHRED_SPLICELEN * chans;
  365. if((dz->lparray[SHR_CHUNKPTR] = (int *)malloc(dz->iparam[SHR_CHCNT] * sizeof(long)))==NULL
  366. || (dz->lparray[SHR_CHUNKLEN] = (int *)malloc(dz->iparam[SHR_CHCNT] * sizeof(long)))==NULL
  367. || (dz->iparray[SHR_PERM] = (int *)malloc(dz->iparam[SHR_CHCNT] * sizeof(int)))==NULL) {
  368. sprintf(errstr,"INSUFFICIENT MEMORY for shredding arrays.\n");
  369. return(MEMORY_ERROR);
  370. }
  371. dz->lparray[SHR_CHUNKPTR][0] = 0; /* first chunk is at start of buffer */
  372. return(FINISHED);
  373. }
  374. /***************************** SHRED_PREPROCESS *************************/
  375. int shred_preprocess(dataptr dz)
  376. {
  377. int sectorcnt;
  378. sectorcnt = dz->insams[0]/dz->buflen;
  379. if(sectorcnt * dz->buflen < dz->insams[0])
  380. sectorcnt++;
  381. if(sectorcnt > 1)
  382. fprintf(stdout,"INFO: File will be shredded in %d distinct sectors.\n",sectorcnt);
  383. fflush(stdout);
  384. return(FINISHED);
  385. }
  386. /***************************CREATE_SHRED_BUFFERS **************************/
  387. //TW replaced by global
  388. //#define SHRED_SECSIZE (256)
  389. /* RWD sigh..... */
  390. int create_shred_buffers(dataptr dz)
  391. {
  392. int exit_status;
  393. int bigfilesize, file_size_in_frames;
  394. double bufs_per_file, lchunkcnt;
  395. size_t basic_bufchunk, bufchunk = (size_t)Malloc(-1);
  396. int framesize = F_SECSIZE * dz->infile->channels;
  397. bigfilesize = dz->insams[0];
  398. if((dz->bigbuf = (float *)malloc((bigfilesize * dz->bufcnt) * sizeof(float)))==NULL) {
  399. bufchunk /= sizeof(float);
  400. basic_bufchunk = bufchunk;
  401. for(;;) {
  402. if((dz->buflen = (int) bufchunk) < 0) {
  403. sprintf(errstr,"INSUFFICIENT MEMORY to allocate sound buffer.\n");
  404. return(MEMORY_ERROR);
  405. }
  406. dz->buflen = (dz->buflen/(framesize * dz->bufcnt)) * framesize * dz->bufcnt;
  407. dz->buflen /= dz->bufcnt;
  408. /* NEW --> */
  409. if(dz->buflen <= 0)
  410. dz->buflen = framesize;
  411. /* <-- NEW */
  412. file_size_in_frames = dz->insams[0]/framesize;
  413. if(framesize * file_size_in_frames < dz->insams[0])
  414. file_size_in_frames++;
  415. bigfilesize = file_size_in_frames * framesize;
  416. if(bigfilesize <= dz->buflen)
  417. dz->buflen = bigfilesize;
  418. if((dz->bigbuf = (float *)malloc((dz->buflen * dz->bufcnt) * sizeof(float)))==NULL) {
  419. sprintf(errstr,"INSUFFICIENT MEMORY to allocate sound buffer.\n");
  420. return(MEMORY_ERROR);
  421. }
  422. if((exit_status = check_for_too_small_buf(dz))>=0)
  423. break;
  424. bufchunk += basic_bufchunk;
  425. }
  426. dz->sampbuf[0] = dz->bigbuf;
  427. dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
  428. if(bigfilesize == dz->buflen) {
  429. dz->iparam[SHR_LAST_BUFLEN] = dz->insams[0]; /* i.e. buflen = true filelen */
  430. dz->iparam[SHR_LAST_CHCNT] = dz->iparam[SHR_CHCNT];
  431. dz->iparam[SHR_LAST_SCAT] = dz->iparam[SHRED_SCAT];
  432. } else {
  433. bufs_per_file = (double)dz->insams[0]/(double)dz->buflen;
  434. lchunkcnt = (double)dz->iparam[SHR_CHCNT]/bufs_per_file;
  435. dz->iparam[SHR_CHCNT] = round(lchunkcnt);
  436. dz->iparam[SHRED_SCAT] = min(dz->iparam[SHRED_SCAT],dz->iparam[SHR_CHCNT]);
  437. dz->iparam[SHR_LAST_BUFLEN] = (dz->insams[0]%dz->buflen);
  438. dz->iparam[SHR_LAST_CHCNT] = round(lchunkcnt*((double)dz->iparam[SHR_LAST_BUFLEN]/(double)dz->buflen));
  439. dz->iparam[SHR_LAST_SCAT] = min(dz->iparam[SHRED_SCAT],dz->iparam[SHR_LAST_CHCNT]);
  440. }
  441. if(dz->iparam[SHR_LAST_CHCNT] < 2) {
  442. fprintf(stdout, "WARNING: FINAL BUFFER WON'T BE SHREDDED (Too short for chunklen set).\n");
  443. fprintf(stdout, "WARNING: It will shred if you\n");
  444. fprintf(stdout, "WARNING: a) shorten infile by (>) chunklen, OR\n");
  445. fprintf(stdout, "WARNING: b) alter chunklen until last buffer has >1 chunk in it.\n");
  446. fflush(stdout);
  447. }
  448. } else {
  449. dz->buflen = bigfilesize;
  450. dz->sampbuf[0] = dz->bigbuf;
  451. dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
  452. dz->iparam[SHR_LAST_BUFLEN] = dz->insams[0]; /* i.e. buflen = true filelen */
  453. dz->iparam[SHR_LAST_CHCNT] = dz->iparam[SHR_CHCNT];
  454. dz->iparam[SHR_LAST_SCAT] = dz->iparam[SHRED_SCAT];
  455. if(dz->iparam[SHR_LAST_CHCNT] < 2) {
  456. fprintf(stdout, "WARNING: FINAL BUFFER WON'T BE SHREDDED (Too short for chunklen set).\n");
  457. fprintf(stdout, "WARNING: It will shred if you\n");
  458. fprintf(stdout, "WARNING: a) shorten infile by (>) chunklen, OR\n");
  459. fprintf(stdout, "WARNING: b) alter chunklen until last buffer has >1 chunk in it.\n");
  460. fflush(stdout);
  461. }
  462. }
  463. memset((char *) (dz->sampbuf[0]),0,(dz->buflen * dz->bufcnt) * sizeof(float));
  464. return(FINISHED);
  465. }
  466. /************************* SHRED_PROCESS ***************************/
  467. int shred_process(dataptr dz)
  468. {
  469. int exit_status;
  470. int n, cnt = 0, checker = 0, work_len;
  471. int current_buf;
  472. if(sloom && dz->iparam[SHRED_SCAT]) {
  473. fprintf(stdout,"WARNING: There is a finite possibility program will not terminate.\n");
  474. fprintf(stdout,"WARNING: If in doubt, press STOP\n");
  475. fflush(stdout);
  476. }
  477. do {
  478. if(!sloom && !sloombatch)
  479. fprintf(stdout,"\nBUFFER %d ",cnt++);
  480. else {
  481. fprintf(stdout,"INFO: BUFFER %d\n",cnt++);
  482. fflush(stdout);
  483. }
  484. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  485. return(exit_status);
  486. current_buf = 0;
  487. if(dz->samps_left <= 0 ) {
  488. dz->buflen = dz->iparam[SHR_LAST_BUFLEN];
  489. dz->iparam[SHRED_SCAT] = dz->iparam[SHR_LAST_SCAT];
  490. dz->iparam[SHR_CHCNT] = dz->iparam[SHR_LAST_CHCNT];
  491. }
  492. if((dz->iparam[SHR_CHCNT_LESS_ONE] = dz->iparam[SHR_CHCNT] - 1)<=0) {
  493. if(cnt==1) {
  494. sprintf(errstr,"SOUNDFILE TOO SMALL to shred.\n");
  495. return(DATA_ERROR);
  496. } else {
  497. n = dz->buflen;
  498. dz->buflen = dz->ssampsread;
  499. do_bufend_splices(current_buf,dz);
  500. if((exit_status = write_exact_samps(dz->sampbuf[current_buf],dz->buflen,dz))<0)
  501. return(exit_status);
  502. dz->buflen = n;
  503. }
  504. } else {
  505. if((exit_status = get_basis_lengths(&work_len,dz))<0)
  506. return(exit_status);
  507. if(!sloom && !sloombatch)
  508. checker = 0;
  509. else
  510. display_virtual_time(0L,dz);
  511. for(n=0;n<dz->iparam[SHRED_CNT];n++) {
  512. if((exit_status = shred(current_buf,work_len,dz))<0)
  513. return(exit_status);
  514. current_buf = !current_buf;
  515. if(!sloom && !sloombatch) {
  516. if(n==checker) {
  517. printf("*");
  518. checker += 16;
  519. }
  520. } else
  521. display_virtual_time((long)n,dz);
  522. }
  523. do_bufend_splices(current_buf,dz);
  524. if((exit_status = write_exact_samps(dz->sampbuf[current_buf],dz->buflen,dz))<0)
  525. return(exit_status);
  526. }
  527. } while(dz->samps_left > 0);
  528. return(FINISHED);
  529. }
  530. /******************************* SHRED **************************
  531. *
  532. * (1) If the random-scattering of chunk boundaries is <= 1.0, scatter
  533. * each chunk boundary separately (normal_scat).
  534. * Else, scatter chunk boundaries over groups of chunklens (heavy_scat).
  535. * (2) Calculate the lengths of the chunks, from difference of their positions.
  536. * (2A) NB the length of the is the difference between its start and
  537. * THE END OF THE work_len (NOT the ned of the buffer). Chunklens are
  538. * measured from start of startsplice to START of endsplice (see
  539. * diagram).
  540. * (3) Generate a permutation (permm[]) of the chunk numbers.
  541. *
  542. * (4) The chunk that is to be FIRST in the permuted set does not need
  543. * to be spliced at its beginning (as there's nothing prior to it,
  544. * to splice into) but only at its end.
  545. * (a) The address from which we copy is position in current buffer
  546. * where chunk associated with 0 (chunk[permm[0]) is.
  547. * (b) The address to copy TO is start of the OTHER buffer (buf[!this]).
  548. * (c) The unit_len of the chunk we're copying is chunklen[permm[0]].
  549. * (d) Copy all of this.
  550. * (f) Copy SPLICELEN extra (full_len is SPLICELEN bigger that unit_len..
  551. * .. see diagram), making an endsplice on it as we do.
  552. *
  553. * (5) For the rest of the chunks APART FROM THE LAST....
  554. * (a) as 4(a): n associated with perm[n]..
  555. * (b) advance in new buffer by chunklen of PREVIOUSLY written chunk..
  556. * This 'length' is length to START of its endsplice, which is where
  557. * new chunk is spliced in.
  558. * (c) as 4(c)
  559. * (d) Do a startsplice as we copy from old_address to new_address.
  560. * (e) Copy from END of this startsplice, a segment of length chnklen
  561. * (length of the total copied chunk) MINUS length of that startsplice
  562. * (SPLICELEN).
  563. * (f) as 4(f).
  564. *
  565. * (6) For the last chunk, we don't need an endsplice (nothing to splice to)
  566. * (a-d)as 5(a-d).
  567. * (e) Copy from end of STARTSPLICE to end of ENDSPLICE ... i.e.
  568. * a whole chunklen, because full_len - SPLICELEN = chunklen.
  569. *
  570. * ___full_len___
  571. * | |
  572. * _chunklen__ |
  573. * | S |
  574. * | T |E
  575. * | R ________|N
  576. * | T/| \D
  577. * | / | \
  578. * |/ | \|
  579. * | |
  580. * |_chunklen_|
  581. * |
  582. * |___full_len___|
  583. *
  584. * (7) Set memory in old buffer to 0 (because we ADD into it, with splices).
  585. */
  586. int shred(int current_buf,int work_len,dataptr dz)
  587. {
  588. int n;
  589. float *old_addr, *new_addr;
  590. int chnk_len;
  591. char *destination = NULL;
  592. int *chunkptr = dz->lparray[SHR_CHUNKPTR];
  593. int *chunklen = dz->lparray[SHR_CHUNKLEN];
  594. int *permm = dz->iparray[SHR_PERM];
  595. if(!dz->iparam[SHRED_SCAT])
  596. normal_scat(dz); /* 1 */
  597. else
  598. heavy_scat(dz);
  599. for(n=0;n<dz->iparam[SHR_CHCNT_LESS_ONE];n++) /* 2 */
  600. chunklen[n] = chunkptr[n+1] - chunkptr[n];
  601. chunklen[n] = work_len - chunkptr[n]; /* 2A */
  602. permute_chunks(dz); /* 3 */
  603. /* NEW FIRST-SEGMENT IN BUFFER */ /* 4 */
  604. old_addr = dz->sampbuf[current_buf] + chunkptr[permm[0]]; /* a */
  605. new_addr = dz->sampbuf[!current_buf]; /* b */
  606. chnk_len = chunklen[permm[0]]; /* c */
  607. if(dz->vflag[0]) {
  608. do_startsplice(old_addr,new_addr,dz);
  609. destination = (char *)(new_addr+dz->iparam[SHRED_SPLEN]);
  610. memcpy(destination,
  611. (char *)(old_addr+dz->iparam[SHRED_SPLEN]),(chnk_len-dz->iparam[SHRED_SPLEN]) * sizeof(float));
  612. } else {
  613. destination = (char *)new_addr;
  614. memcpy(destination,(char *)old_addr,chnk_len*sizeof(float));
  615. }
  616. do_endsplice(old_addr+chnk_len, new_addr+chnk_len,dz); /* f */
  617. /* MIDDLE-SEGMENTS IN BUFFER */ /* 5 */
  618. for(n=1;n<dz->iparam[SHR_CHCNT_LESS_ONE];n++) {
  619. old_addr = dz->sampbuf[current_buf] + chunkptr[permm[n]]; /* a */
  620. new_addr += chnk_len; /* b */
  621. chnk_len = chunklen[permm[n]]; /* c */
  622. do_startsplice(old_addr,new_addr,dz); /* d */
  623. destination = (char *)(new_addr+dz->iparam[SHRED_SPLEN]);
  624. memcpy(destination,
  625. (char *)(old_addr+dz->iparam[SHRED_SPLEN]),(chnk_len-dz->iparam[SHRED_SPLEN]) * sizeof(float));
  626. do_endsplice(old_addr+chnk_len,new_addr+chnk_len,dz);
  627. } /* f */
  628. /* NEW END-SEGMENT IN BUFFER */ /* 6 */
  629. old_addr = dz->sampbuf[current_buf] + chunkptr[permm[n]]; /* a */
  630. new_addr += chnk_len; /* b */
  631. chnk_len = chunklen[permm[n]]; /* c */
  632. do_startsplice(old_addr,new_addr,dz); /* d */
  633. if(dz->vflag[0])
  634. do_endsplice(old_addr+chnk_len,new_addr+chnk_len,dz);
  635. destination = (char *)(new_addr+dz->iparam[SHRED_SPLEN]);
  636. memcpy(destination,(char *)(old_addr+dz->iparam[SHRED_SPLEN]),chnk_len*sizeof(float));
  637. /* RESET BUFFERS */
  638. memset((char *)dz->sampbuf[current_buf],0,dz->buflen * sizeof(float)); /* 7 */
  639. return(FINISHED);
  640. }
  641. /*********************** GET_BASIS_LENGTHS **********************
  642. *
  643. *
  644. * ______________buflen_______________
  645. * |............worklen............. | buflen - SPLICELEN = worklen.
  646. * | unitlen unitlen | | unit_len * dz->iparam[SHR_CHCNT] = worklen.
  647. * | | | | |
  648. * |_full_len_ | _full_len__| full_len = worklen + SPLICELEN.
  649. * | | | | | | |
  650. * | _____| |_____| ____| _____| |
  651. * | /| \ / \ / \ / \ |
  652. * | / | |X| X X \ |
  653. * |/ | / \ / \ / \ \|
  654. * | | |
  655. * | | |
  656. * rawlen
  657. *
  658. *
  659. */
  660. int get_basis_lengths(int *work_len,dataptr dz)
  661. {
  662. int excess, full_len, endunit_len, endfull_len;
  663. *work_len = dz->buflen - dz->iparam[SHRED_SPLEN];
  664. dz->iparam[SHR_UNITLEN] = (int)round((*work_len)/dz->iparam[SHR_CHCNT]);
  665. excess = dz->iparam[SHR_UNITLEN] % dz->infile->channels;
  666. dz->iparam[SHR_UNITLEN] -= excess;
  667. excess = (*work_len) - (dz->iparam[SHR_UNITLEN] * dz->iparam[SHR_CHCNT]);
  668. if(excess % dz->infile->channels) {
  669. sprintf(errstr,"Problem in buffer accounting.\n");
  670. return(PROGRAM_ERROR);
  671. }
  672. dz->iparam[SHR_RAWLEN] = dz->iparam[SHR_UNITLEN] - dz->iparam[SHRED_SPLEN];
  673. full_len = dz->iparam[SHR_UNITLEN] + dz->iparam[SHRED_SPLEN];
  674. endunit_len = dz->iparam[SHR_UNITLEN] + excess;
  675. endfull_len = full_len + excess;
  676. dz->iparam[SHR_ENDRAWLEN] = dz->iparam[SHR_RAWLEN] + excess;
  677. if(full_len < (dz->iparam[SHRED_SPLEN] * 2) || endfull_len < (dz->iparam[SHRED_SPLEN] * 2)) {
  678. sprintf(errstr,"Chunksize too small for splices.\n");
  679. return(DATA_ERROR);
  680. }
  681. if(dz->iparam[SHRED_SCAT]) {
  682. dz->iparam[SHR_SCATGRPCNT] = (int)(dz->iparam[SHR_CHCNT]/dz->iparam[SHRED_SCAT]);
  683. dz->iparam[SHR_ENDSCAT] = (int)(dz->iparam[SHR_CHCNT] - (dz->iparam[SHR_SCATGRPCNT] * dz->iparam[SHRED_SCAT]));
  684. dz->iparam[SHR_RANGE] = dz->iparam[SHR_UNITLEN] * dz->iparam[SHRED_SCAT];
  685. dz->iparam[SHR_ENDRANGE] = ((dz->iparam[SHR_ENDSCAT]-1) * dz->iparam[SHR_UNITLEN]) + endunit_len;
  686. }
  687. return(FINISHED);
  688. }
  689. /************************** NORMAL_SCAT ******************************
  690. *
  691. * (1) TOTLA_LEN generates the unscattered positions of the chunks.
  692. * Each is UNIT_LEN long, so they are equally spaced at UNIT_LEN
  693. * intervals.
  694. We can't scatter the FIRST chunk as it MUST start at ZERO!!
  695. * (2) For all chunks except the first and last...
  696. * (3) Scatter position of chunk over +- 1/2 of value of scatter,
  697. * times the RAW-distance (not including splices) between chunks.
  698. * (4) Add (could be negative) this scattering to orig position.
  699. * (5) For the last chunk, do the same, scattering over RAW-len of previous
  700. * chunk, if scatter -ve, and over endraw_len of final chunk, if +ve.
  701. */
  702. void normal_scat(dataptr dz)
  703. {
  704. double this_scatter;
  705. int n, k;
  706. int chunkscat, total_len = dz->iparam[SHR_UNITLEN]; /* 1 */
  707. int *chunkptr = dz->lparray[SHR_CHUNKPTR];
  708. for(n=1;n<dz->iparam[SHR_CHCNT_LESS_ONE];n++) { /* 2 */
  709. this_scatter = (drand48() - 0.5) * dz->param[SHRED_SCAT];
  710. chunkscat = (int)(this_scatter * (double)dz->iparam[SHR_RAWLEN]);
  711. k = chunkscat % dz->infile->channels;
  712. chunkscat -= k;
  713. chunkptr[n] = total_len + chunkscat;
  714. total_len += dz->iparam[SHR_UNITLEN]; /* 4 */
  715. }
  716. this_scatter = (drand48() - 0.5) * dz->param[SHRED_SCAT];
  717. if(this_scatter<0.0) { /* 5 */
  718. chunkscat = (int)(this_scatter * (double)dz->iparam[SHR_RAWLEN]);
  719. k = chunkscat % dz->infile->channels;
  720. chunkscat -= k;
  721. chunkptr[n] = total_len - chunkscat;
  722. } else {
  723. chunkscat = (int)(this_scatter * (double)dz->iparam[SHR_ENDRAWLEN]);
  724. k = chunkscat % dz->infile->channels;
  725. chunkscat -= k;
  726. chunkptr[n] = total_len + chunkscat;
  727. }
  728. }
  729. /*********************** HEAVY_SCAT ***************************
  730. *
  731. * (1) Start at the chunk (this=1) AFTER the first (which can't be moved).
  732. * (2) STARTPTR marks the start of the chunk GROUP (and will be advanced
  733. * by RANGE, which is length of chunk-group).
  734. * (3) The loop will generate a set of positions for the chunks in
  735. * a chunk-group. In the first chunkgroup the position of the
  736. * first chunk (start of file) can't be moved, so loop starts at
  737. * (first=) 1. Subsequemt loop passes start at 0.
  738. * (4) For eveery chunk-group.
  739. * (5) Set the index of the first chunk in this group (start) to the
  740. * current index (this).
  741. * (6) For every member of this chunk-group.
  742. * (7) Generate a random-position within the chunk-grp's range
  743. * and check it is not too close ( < SPLICELEN) to the others.
  744. * Set a checking flag (OK).
  745. * (8) Generate a position within the range, and after the startptr.
  746. * (9) Compare it with all previously generated positions in this
  747. * chunk-grp AND with last position of previous chunk-group!!
  748. * If it's closer than SPLICELEN, set OK = 0, drop out of
  749. checking loop and generate another position instead.
  750. * (10) If the position is OK, drop out of position generating loop..
  751. * (11) Advance to next chunk in this group.
  752. * (12) Once all this group is done, advance the group startpoint by RANGE.
  753. * (13) After FIRST grp, all positions can by varied, so set the initial
  754. * loop counter to (first=)0.
  755. * (14) If there are chunks left over (endscat!=0)..
  756. * Follow the same procedure for chunks in end group, using the
  757. * alternative variables, endscat and endrange.
  758. */
  759. void heavy_scat(dataptr dz)
  760. {
  761. int thiss = 1, that, start, n, m, OK; /* 1 */
  762. int k;
  763. int startptr = 0; /* 2 */
  764. int endptr = 0;
  765. int first = 1; /* 3 */
  766. int *chunkptr = dz->lparray[SHR_CHUNKPTR];
  767. for(n=0;n<dz->iparam[SHR_SCATGRPCNT];n++) { /* 4 */
  768. start = thiss; /* 5 */
  769. endptr += dz->iparam[SHR_RANGE];
  770. for(m=first;m<dz->iparam[SHRED_SCAT];m++) { /* 6 */
  771. do{ /* 7 */
  772. OK = 1;
  773. chunkptr[thiss] = (long)(drand48()*dz->iparam[SHR_RANGE]); /* TRUNCATE (?)*/
  774. chunkptr[thiss] += startptr; /* 8 */
  775. k = chunkptr[thiss] % dz->infile->channels;
  776. chunkptr[thiss] -= k;
  777. for(that=start-1; that<thiss; that++) {
  778. if(abs(chunkptr[thiss] - chunkptr[that])<dz->iparam[SHRED_SPLEN]) {
  779. OK = 0; /* 9 */
  780. break;
  781. }
  782. if(abs(endptr - chunkptr[thiss])<dz->iparam[SHRED_SPLEN]) {
  783. OK = 0;
  784. break;
  785. }
  786. }
  787. } while(!OK); /* 10 */
  788. thiss++; /* 11 */
  789. }
  790. startptr += dz->iparam[SHR_RANGE]; /* 12 */
  791. first = 0; /* 13 */
  792. }
  793. endptr += dz->iparam[SHR_ENDRANGE];
  794. if(dz->iparam[SHR_ENDSCAT]) { /* 14 */
  795. start = thiss;
  796. for(m=0;m<dz->iparam[SHR_ENDSCAT];m++) {
  797. do {
  798. OK = 1;
  799. chunkptr[thiss] = (long)(drand48() * dz->iparam[SHR_ENDRANGE]); /* TRUNCATE (?) */
  800. chunkptr[thiss] += startptr;
  801. k = chunkptr[thiss] % dz->infile->channels;
  802. chunkptr[thiss] -= k;
  803. for(that=start-1; that<thiss; that++) {
  804. if(abs(chunkptr[thiss] - chunkptr[that])<dz->iparam[SHRED_SPLEN]) {
  805. OK = 0;
  806. break;
  807. }
  808. if(abs(endptr - chunkptr[thiss])<dz->iparam[SHRED_SPLEN]) {
  809. OK = 0;
  810. break;
  811. }
  812. }
  813. } while(!OK);
  814. thiss++;
  815. }
  816. }
  817. ptr_sort(thiss,dz);
  818. }
  819. /*************************** PERMUTE_CHUNKS ***************************/
  820. void permute_chunks(dataptr dz)
  821. {
  822. int n, t;
  823. for(n=0;n<dz->iparam[SHR_CHCNT];n++) {
  824. t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
  825. if(t==n)
  826. prefix(n,dz);
  827. else
  828. insert(n,t,dz);
  829. }
  830. }
  831. /****************************** INSERT ****************************/
  832. void insert(int n,int t,dataptr dz)
  833. {
  834. shuflup(t+1,dz);
  835. dz->iparray[SHR_PERM][t+1] = n;
  836. }
  837. /****************************** PREFIX ****************************/
  838. void prefix(int n,dataptr dz)
  839. {
  840. shuflup(0,dz);
  841. dz->iparray[SHR_PERM][0] = n;
  842. }
  843. /****************************** SHUFLUP ****************************/
  844. void shuflup(int k,dataptr dz)
  845. {
  846. int n;
  847. for(n = dz->iparam[SHR_CHCNT_LESS_ONE]; n > k; n--)
  848. dz->iparray[SHR_PERM][n] = dz->iparray[SHR_PERM][n-1];
  849. }
  850. /************************* DO_STARTSPLICE *************************
  851. *
  852. * (0) For each position in splice.
  853. * (1) Get the value from the source file & multiply it by position in splice.
  854. * We 'should' multiply it by position/SPLICELEN,
  855. * so new value is SPLICELEN too large.
  856. * (2) Add a rounding factor (if value were correct, this would be 1/2)
  857. * But everything is SPLICELEN times too big, so add SHRED_HSPLICELEN.
  858. * (3) Divide by SPLICELEN.
  859. * (4) ADD this value to existing value (this is a splice TO another chunk!!).
  860. */
  861. void do_startsplice(float *i,float *j,dataptr dz)
  862. {
  863. double z;
  864. int n;
  865. for(n = 0; n <dz->iparam[SHRED_SPLEN]; n ++) { /* 0 */
  866. z = (*i) * (double)n/dz->iparam[SHRED_SPLEN]; /* 1 */
  867. i++;
  868. *j = (float) /*round*/((*j) + z); /* 4 */
  869. j++;
  870. }
  871. }
  872. /************************* DO_ENDSPLICE *************************/
  873. void do_endsplice(float *i,float *j,dataptr dz)
  874. {
  875. double z;
  876. int n;
  877. for(n = dz->iparam[SHRED_SPLEN]-1; n>=0; n--) {
  878. z = *i++ * (double)n/dz->iparam[SHRED_SPLEN];
  879. *j++ += (float) /*round*/ (z);
  880. }
  881. }
  882. /********************* DO_BUFEND_SPLICES *************************/
  883. void do_bufend_splices(int current_buf,dataptr dz)
  884. {
  885. double z;
  886. int n;
  887. float *b = dz->sampbuf[current_buf];
  888. for(n = 0; n <dz->iparam[SHRED_SPLEN]; n ++) {
  889. z = (*b) * (double)n/dz->iparam[SHRED_SPLEN];
  890. *b++ = (float)z;
  891. }
  892. b = dz->sampbuf[current_buf] + dz->buflen - dz->iparam[SHRED_SPLEN];
  893. for(n = dz->iparam[SHRED_SPLEN]-1; n>=0; n--) {
  894. z = (*b) * (double)n/dz->iparam[SHRED_SPLEN];
  895. *b++ = (float) /*round*/(z);
  896. }
  897. }
  898. /**************************** CHECK_FOR_TOO_SMALL_BUF *********************/
  899. int check_for_too_small_buf(dataptr dz)
  900. {
  901. int chunksamps = round(dz->param[SHRED_CHLEN] * dz->infile->srate) * dz->infile->channels;
  902. if(dz->iparam[SHRED_SCAT]) {
  903. if(dz->buflen <= chunksamps * dz->iparam[SHRED_SCAT]) {
  904. sprintf(errstr,"Internal sound buffer too short (%lf secs) for chunksize and scatter.\n",
  905. (double)(dz->buflen/dz->infile->channels)/(double)dz->infile->srate);
  906. return(GOAL_FAILED);
  907. }
  908. } else {
  909. if(dz->buflen <= chunksamps * 2) {
  910. sprintf(errstr,"Sound buffer too short for chunksize.\n");
  911. return(GOAL_FAILED);
  912. }
  913. }
  914. return(FINISHED);
  915. }
  916. /************************** PTR_SORT ***************************/
  917. void ptr_sort(int end,dataptr dz)
  918. {
  919. int i,j;
  920. int a;
  921. int *chunkptr = dz->lparray[SHR_CHUNKPTR];
  922. for(j=1;j<end;j++) {
  923. a = chunkptr[j];
  924. i = j-1;
  925. while(i >= 0 && chunkptr[i] > a) {
  926. chunkptr[i+1]=chunkptr[i];
  927. i--;
  928. }
  929. chunkptr[i+1] = a;
  930. }
  931. }
  932. /*************************** SCRUB_PCONSISTENCY **************************/
  933. int scrub_pconsistency(dataptr dz)
  934. {
  935. if(dz->param[SCRUB_MINSPEED] > dz->param[SCRUB_MAXSPEED])
  936. swap(&(dz->param[SCRUB_MINSPEED]),&dz->param[SCRUB_MAXSPEED]);
  937. dz->iparam[SCRUB_TOTALDUR] = round(dz->param[SCRUB_TOTALDUR] * (double)(dz->infile->srate * dz->infile->channels));
  938. return(FINISHED);
  939. }
  940. /*************************** SCRUB_PREPROCESS **************************/
  941. int scrub_preprocess(dataptr dz)
  942. {
  943. int exit_status;
  944. double sr = (double)dz->infile->srate;
  945. int chans = dz->infile->channels;
  946. initrand48();
  947. if((exit_status = create_sintable(dz))<0)
  948. return(exit_status);
  949. dz->iparam[SCRUB_STARTRANGE] = round(dz->param[SCRUB_STARTRANGE] * sr);
  950. dz->iparam[SCRUB_ESTART] = round(dz->param[SCRUB_ESTART] * sr);
  951. dz->iparam[SCRUB_ENDRANGE] = (dz->insams[0]/chans) - dz->iparam[SCRUB_ESTART];
  952. dz->param[SCRUB_SPEEDRANGE] = dz->param[SCRUB_MAXSPEED] - dz->param[SCRUB_MINSPEED];
  953. return(FINISHED);
  954. }
  955. /*************************** CREATE_SINTABLE **************************/
  956. int create_sintable(dataptr dz)
  957. {
  958. int n;
  959. /* GENERATE A WARPED SINUS TABLE, Range 0 - 1 */
  960. if((dz->parray[SCRUB_SIN] = (double *)malloc((SCRUB_SINTABSIZE+1) * sizeof(double)))==NULL) {
  961. sprintf(errstr,"INSUFFICIENT MEMORY to create sintable for scrubbing.\n");
  962. return(MEMORY_ERROR);
  963. }
  964. for(n=0;n<SCRUB_SINTABSIZE;n++) {
  965. dz->parray[SCRUB_SIN][n] = sin(PI * (double)n/(double)SCRUB_SINTABSIZE);
  966. dz->parray[SCRUB_SIN][n] = pow(dz->parray[SCRUB_SIN][n],SCRUB_SINWARP);
  967. }
  968. dz->parray[SCRUB_SIN][n] = 0.0;
  969. if((dz->parray[SCRUB_READTAB] = (double *)malloc((SCRUB_SINTABSIZE+1) * sizeof(double)))==NULL) {
  970. sprintf(errstr,"INSUFFICIENT MEMORY to create skewtable for scrubbing.\n");
  971. return(MEMORY_ERROR);
  972. }
  973. return(FINISHED);
  974. }
  975. /***************************CREATE_BUFFERS **************************/
  976. int create_scrub_buffers(dataptr dz)
  977. {
  978. size_t bigbufsize;
  979. long shsecsize = F_SECSIZE, sum = 0L;
  980. long framesize = F_SECSIZE * dz->infile->channels;
  981. bigbufsize = (size_t)Malloc(-1);
  982. bigbufsize /= sizeof(float);
  983. bigbufsize = (bigbufsize/(framesize*dz->bufcnt)) * framesize * dz->bufcnt;
  984. bigbufsize = bigbufsize/dz->bufcnt;
  985. if(bigbufsize <= 0)
  986. bigbufsize = framesize;
  987. dz->buflen = (int) bigbufsize;
  988. if((dz->bigbuf = (float *)malloc(
  989. ((dz->buflen * dz->bufcnt) + (F_SECSIZE*2)) * sizeof(float))) == NULL) {
  990. sprintf(errstr, "INSUFFICIENT MEMORY for sound buffers.\n");
  991. return(MEMORY_ERROR);
  992. }
  993. dz->sampbuf[0] = dz->bigbuf;
  994. dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen + (shsecsize*2); /* inbuf has wraparound sectors */
  995. dz->iparam[SCRUB_DROPOUT] = FALSE;
  996. if(dz->iparam[SCRUB_TOTALDUR] <= dz->buflen + shsecsize) {
  997. dz->buflen = dz->iparam[SCRUB_TOTALDUR];
  998. dz->iparam[SCRUB_DROPOUT] = TRUE;
  999. }
  1000. dz->iparam[SCRUB_BUFCNT] = 0;
  1001. while(sum < dz->insams[0]) {
  1002. dz->iparam[SCRUB_BUFCNT]++;
  1003. sum += dz->buflen;
  1004. }
  1005. return(FINISHED);
  1006. }
  1007. /****************************** DO_SCRUBBING *************************/
  1008. int do_scrubbing(dataptr dz)
  1009. {
  1010. int exit_status;
  1011. /* float *ibuf = dz->sampbuf[0];*/
  1012. float *obuf = dz->sampbuf[1];
  1013. int chans = dz->infile->channels;
  1014. int scrublen_in_src, effective_tablen;
  1015. double skew, lospeed,speedrange;
  1016. int direction = SCRUB_BACKWARDS, here, lasthere = 0, there = 0;
  1017. display_virtual_time(0,dz); /* fraction of total_dur!! */
  1018. get_end(&direction,&lasthere,dz); /* setup start position */
  1019. do {
  1020. here = lasthere;
  1021. get_end(&direction,&here,dz);
  1022. skew = get_skew();
  1023. get_speed(&lospeed,&speedrange,dz);
  1024. scrublen_in_src = abs(here - lasthere);
  1025. effective_tablen = gen_readtab(skew,lospeed,speedrange,scrublen_in_src,dz);
  1026. if((exit_status = scrub(&lasthere,&there,!direction,effective_tablen,dz))<0)
  1027. return(exit_status);
  1028. if(exit_status == FINISHED)
  1029. break;
  1030. if(dz->vflag[0]) // FORWARD SCRUB ONLY
  1031. break;
  1032. } while((there * chans) + dz->total_samps_written < dz->iparam[SCRUB_TOTALDUR]);
  1033. if(there > 0)
  1034. return write_samps(obuf,there * chans,dz);
  1035. return(FINISHED);
  1036. }
  1037. /******************************* GET_SKEW ******************************/
  1038. double get_skew(void)
  1039. { double skew;
  1040. skew = (drand48() * 2.0) - 1.0; /* -1 to +1 */
  1041. skew *= SCRUB_SKEWRANGE;
  1042. skew += 1.0; /* 1 +- SKEWRANGE */
  1043. return(skew);
  1044. }
  1045. /******************************* GET_SPEED ******************************
  1046. *
  1047. * Generate a speed distribution which is pitch (not frq) distributed.
  1048. */
  1049. void get_speed(double *lospeed,double *speedrang,dataptr dz)
  1050. {
  1051. double hispeed;
  1052. hispeed = drand48() * dz->param[SCRUB_SPEEDRANGE] * SCRUB_RANGE_REDUCE_FACTOR;
  1053. hispeed = dz->param[SCRUB_MAXSPEED] - hispeed;
  1054. *lospeed = drand48() * dz->param[SCRUB_SPEEDRANGE] * SCRUB_RANGE_REDUCE_FACTOR;
  1055. *lospeed += dz->param[SCRUB_MINSPEED];
  1056. *speedrang = hispeed - *lospeed;
  1057. }
  1058. /******************************* GET_END ******************************/
  1059. void get_end(int *direction,int *here,dataptr dz)
  1060. {
  1061. int lasthere = *here;
  1062. switch(*direction) {
  1063. case(SCRUB_FORWARDS):
  1064. *here = round(drand48() * dz->iparam[SCRUB_ENDRANGE]);
  1065. *here += dz->iparam[SCRUB_ESTART];
  1066. *direction = SCRUB_BACKWARDS;
  1067. break;
  1068. case(SCRUB_BACKWARDS):
  1069. *here = round(drand48() * dz->iparam[SCRUB_STARTRANGE]);
  1070. *direction = SCRUB_FORWARDS;
  1071. break;
  1072. }
  1073. //TW COMMENT: this statement has no effect
  1074. dz->param[SCRUB_LENGTH] = abs(lasthere - *here);
  1075. }
  1076. /***************************** GEN_READTAB *****************************/
  1077. int gen_readtab(double skew,double lospeed,double speedrange,int scrublen_in_src,dataptr dz)
  1078. {
  1079. int n, here, next, tablen = -1;
  1080. double step, sin_index, frac, dindex;
  1081. double *sintab = dz->parray[SCRUB_SIN];
  1082. double *readtab = dz->parray[SCRUB_READTAB];
  1083. double readtab_integral = 0.0, last_readtab_integral, searchstep = 1.01;
  1084. /* GENERATE A SKEWED WARPED-SINUS-TABLE, Range 0 - 1, from orig WARPED-SINUS-TABLE */
  1085. if(flteq(skew,1.0)) {
  1086. memcpy((char *)readtab,(char *)sintab,(SCRUB_SINTABSIZE + 1) * sizeof(double));
  1087. tablen = SCRUB_SINTABSIZE;
  1088. } else {
  1089. sin_index = 0.0;
  1090. step = (double)SCRUB_SINTABSIZE * (1.0-skew); /* initial step found using */
  1091. step /= (1.0 - pow(skew,(double)SCRUB_SINTABSIZE)); /* geometric series sum */
  1092. readtab[0] = 0.0;
  1093. for(n=1;n<SCRUB_SINTABSIZE;n++) {
  1094. sin_index += step;
  1095. if((here = (int)sin_index) >= SCRUB_SINTABSIZE) { /* TRUNCATE */
  1096. tablen = n;
  1097. sprintf(errstr,"scrubbing table incomplete by %d items\n",SCRUB_SINTABSIZE - n);
  1098. print_outwarning_flush(errstr);
  1099. break;
  1100. } else {
  1101. frac = sin_index - (double)here;
  1102. next = here + 1;
  1103. readtab[n] = (sintab[next] - sintab[here]) * frac;
  1104. readtab[n] += sintab[here];
  1105. step *= skew;
  1106. }
  1107. }
  1108. if(tablen < 0)
  1109. tablen = SCRUB_SINTABSIZE;
  1110. readtab[tablen] = readtab[tablen-1];
  1111. }
  1112. for(n=0;n<=tablen;n++) {
  1113. /* range is initially 0 - 1 */
  1114. readtab[n] *= speedrange; /* change scale to range of speedrange */
  1115. readtab[n] += lospeed; /* shift values to be within range lospeed to hispeed */
  1116. readtab[n] *= OCTAVES_PER_SEMITONE; /* convert values to octaves */
  1117. readtab[n] = pow(2.0,readtab[n]); /* convert vals to transposition ratios = increments in infile */
  1118. readtab_integral += readtab[n]; /* integrate func to get total length */
  1119. }
  1120. /* If the speedvary process causes sample-read to fall off end of file */
  1121. /* move more quickly through the sample-read-incrs file */
  1122. while(readtab_integral >= (double)scrublen_in_src) {
  1123. last_readtab_integral = readtab_integral;
  1124. dz->param[SCRUB_TABINC] = readtab_integral/(double)scrublen_in_src;
  1125. dindex = 0.0;
  1126. readtab_integral = 0.0;
  1127. while(dindex <= (double)tablen) {
  1128. here = (int)floor(dindex);
  1129. next = here+1;
  1130. frac = dindex - (double)here;
  1131. readtab_integral += (readtab[n] * (1.0 - frac)) + (readtab[next] * frac);
  1132. dindex += dz->param[SCRUB_TABINC];
  1133. }
  1134. if(last_readtab_integral == readtab_integral) {
  1135. /* if the search process stalls, kick restart it */
  1136. readtab_integral *= searchstep;
  1137. searchstep *= searchstep;
  1138. }
  1139. }
  1140. /* in effect: change area under function by expanding or contracting it along x-axis */
  1141. dz->param[SCRUB_TABINC] = readtab_integral/(double)scrublen_in_src;
  1142. return tablen;
  1143. }
  1144. /**************************** SCRUB *******************************/
  1145. #define SCRUB_SPLICE (0.1)
  1146. int scrub(int *hhere,int *tthere,int direction,int effective_tablen,dataptr dz)
  1147. {
  1148. int exit_status, scrub_exit_status;
  1149. int index;
  1150. double lfrac, inval;
  1151. int n, m;
  1152. int chans = dz->infile->channels;
  1153. int effective_buflen = dz->buflen/chans;
  1154. int abshere = *hhere, there = *tthere;
  1155. int here = abshere % effective_buflen;
  1156. int bufno = abshere/effective_buflen; /* TRUNCATE */
  1157. int truehere, truethere;
  1158. int cnt = 0, splicend, scrubend = 0;
  1159. double splincr, splval;
  1160. double dindex, dhere = here, frac, val;
  1161. float *ibuf = dz->sampbuf[0];
  1162. float *obuf = dz->sampbuf[1];
  1163. double *readtab = dz->parray[SCRUB_READTAB];
  1164. if((exit_status = read_samps_for_scrub(bufno,dz))<0) /* read wraparound buffer */
  1165. return(exit_status);
  1166. if(there >= effective_buflen) {
  1167. if(dz->iparam[SCRUB_DROPOUT])
  1168. return(FINISHED);
  1169. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1170. return(exit_status);
  1171. there = 0;
  1172. truethere = there *chans;
  1173. }
  1174. for(m=0;m<chans;m++)
  1175. obuf[(there*chans)+m] = 0.0f;
  1176. splicend = (int)round((double)dz->infile->srate * SCRUB_SPLICE);
  1177. dindex = dz->param[SCRUB_TABINC];
  1178. while (dindex < (double)effective_tablen) {
  1179. dindex += dz->param[SCRUB_TABINC];
  1180. scrubend++;
  1181. }
  1182. scrubend -= splicend;
  1183. if(scrubend < splicend) {
  1184. scrubend += splicend;
  1185. splicend = scrubend/2;
  1186. scrubend -= splicend;
  1187. }
  1188. splincr = 1.0/(double)splicend;
  1189. splval = splincr;
  1190. dindex = dz->param[SCRUB_TABINC];
  1191. there++;
  1192. truethere = there *chans;
  1193. do {
  1194. if(there >= effective_buflen) {
  1195. if(dz->iparam[SCRUB_DROPOUT])
  1196. return(FINISHED);
  1197. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1198. return(exit_status);
  1199. there = 0;
  1200. truethere = there *chans;
  1201. }
  1202. index = (long)dindex; /* TRUNCATE */ /* interpolate vals in readtable */
  1203. frac = dindex - (double)index;
  1204. val = (readtab[index+1] - readtab[index]) * frac;
  1205. val += readtab[index];
  1206. scrub_exit_status = CONTINUE;
  1207. if(direction==SCRUB_FORWARDS) {
  1208. dhere += val; /* use readtab val to interpolate in sndfile */
  1209. here = (int)dhere; /* TRUNCATE */
  1210. truehere = here * chans;
  1211. if(truehere >= dz->ssampsread) {
  1212. if(++bufno >= dz->iparam[SCRUB_BUFCNT]) {
  1213. fprintf(stdout,"WARNING: overreached infile.\n");
  1214. fflush(stdout);
  1215. scrub_exit_status = FINISHED;
  1216. break;
  1217. }
  1218. if((exit_status = read_samps_for_scrub(bufno,dz))<0) /* read wraparound buffer */
  1219. return(exit_status);
  1220. truehere -= dz->buflen;
  1221. here -= effective_buflen;
  1222. dhere -= (double)effective_buflen;
  1223. }
  1224. } else {
  1225. dhere -= val;
  1226. here = (int)dhere; /* TRUNCATE */
  1227. truehere = here * chans;
  1228. if(here < 0) {
  1229. if(--bufno < 0) {
  1230. fprintf(stdout,"WARNING: fell off start of infile.\n");
  1231. fflush(stdout);
  1232. scrub_exit_status = FINISHED;
  1233. break;
  1234. }
  1235. if((exit_status = read_samps_for_scrub(bufno,dz))<0) /* read wraparound buffer */
  1236. return(exit_status);
  1237. truehere += dz->buflen;
  1238. here += effective_buflen;
  1239. dhere += (double)effective_buflen;
  1240. }
  1241. }
  1242. lfrac = dhere - (double)here;
  1243. if (cnt > scrubend) {
  1244. for(m=0;m<chans;m++) {
  1245. inval = ibuf[truehere+m] * (1.0 - lfrac);
  1246. inval += ibuf[truehere+m+chans] * lfrac;
  1247. obuf[truethere+m] = (float)(inval * splval);
  1248. splval -= splincr;
  1249. }
  1250. } else if(cnt < splicend) {
  1251. for(m=0;m<chans;m++) {
  1252. inval = ibuf[truehere+m] * (1.0 - lfrac);
  1253. inval += ibuf[truehere+m+chans] * lfrac;
  1254. obuf[truethere+m] = (float)(inval * splval);
  1255. splval += splincr;
  1256. }
  1257. } else {
  1258. for(m=0;m<chans;m++) {
  1259. inval = ibuf[truehere+m] * (1.0 - lfrac);
  1260. inval += ibuf[truehere+m+chans] * lfrac;
  1261. obuf[truethere+m] = (float) /*round*/(inval);
  1262. }
  1263. }
  1264. there++;
  1265. truethere = there *chans;
  1266. cnt++;
  1267. } while ((dindex += dz->param[SCRUB_TABINC]) < SCRUB_SINTABSIZE);
  1268. for(n=0;n<SCRUB_SINTABSIZE;n++) { /* create silent gap to avoid clicks */
  1269. if(there >= effective_buflen) {
  1270. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1271. return(exit_status);
  1272. there = 0;
  1273. truethere = 0;
  1274. }
  1275. for(m=0;m<chans;m++)
  1276. obuf[truethere+m] = 0.0f;
  1277. truethere += chans;
  1278. there++;
  1279. }
  1280. *hhere = (bufno * effective_buflen) + here;
  1281. *tthere = there;
  1282. return(scrub_exit_status);
  1283. }
  1284. /**************************** READ_SAMPS_FOR_SCRUB *******************************/
  1285. int read_samps_for_scrub(int bufno,dataptr dz)
  1286. {
  1287. int exit_status;
  1288. float *buf = dz->sampbuf[0];
  1289. if(sndseekEx(dz->ifd[0],bufno * dz->buflen,0)<0) {
  1290. sprintf(errstr,"sndseek() 1 failed in scrub.\n"); /* seek to start of buffer from which to read */
  1291. return(SYSTEM_ERROR);
  1292. }
  1293. dz->buflen += F_SECSIZE; /* samps to read, with F_SECSIZE wraparound for interpd reading last sample in buf */
  1294. /* zeroes buffer in case wraparound on last-samp-in-file !! */
  1295. memset((char *)buf,0,(dz->buflen + F_SECSIZE) * sizeof(float));
  1296. /* zeros FURTHER F_SECSIZE samps in case file exactly fills the F_SECSIZE-extended buffer */
  1297. /* & there's wraparound on last-samp-in-file !! */
  1298. if((exit_status = read_samps(buf,dz))<0) /* read wraparound buffer */
  1299. return(exit_status);
  1300. dz->buflen -= F_SECSIZE; /* reset to unwrapped buffer size */
  1301. if(dz->ssampsread > dz->buflen) /* if read beyond effective bufsize, there are samps in file beyond this */
  1302. dz->ssampsread = dz->buflen; /* reset samps_read to non-wrapped samps read */
  1303. return(FINISHED);
  1304. }
  1305. /*************************** CROSSMOD_PCONSISTENCY **************************/
  1306. int crossmod_pconsistency(dataptr dz)
  1307. {
  1308. if(dz->infile->srate != dz->otherfile->srate) {
  1309. sprintf(errstr,"Cross modulation only works with files of same srate.\n");
  1310. return(DATA_ERROR);
  1311. }
  1312. if((dz->otherfile->channels > 2 && dz->infile->channels != 1) || (dz->infile->channels > 2 && dz->otherfile->channels != 1)) {
  1313. if(dz->infile->channels != dz->otherfile->channels) {
  1314. sprintf(errstr,"With multichannel files, Cross modulation ONLY works if files have same number of channels OR if one file is mono.\n");
  1315. return(DATA_ERROR);
  1316. }
  1317. }
  1318. return(FINISHED);
  1319. }
  1320. /*************************** CREATE_CROSSMOD_BUFFERS **************************/
  1321. //TW replaced by global
  1322. //#define FSECSIZE (256)
  1323. int create_crossmod_buffers(dataptr dz)
  1324. {
  1325. size_t bigbufsize;
  1326. int framesize;
  1327. int bufchunks;
  1328. bufchunks = dz->infile->channels;
  1329. bufchunks += dz->otherfile->channels;
  1330. bufchunks += max(dz->otherfile->channels,dz->infile->channels);
  1331. bigbufsize = (size_t)Malloc(-1);
  1332. dz->buflen = (int)(bigbufsize / sizeof(float));
  1333. //TW MODIFIED ....
  1334. framesize = F_SECSIZE * bufchunks;
  1335. if((dz->buflen = (dz->buflen/framesize) * framesize)<=0)
  1336. dz->buflen = framesize;
  1337. if((dz->bigbuf = (float *)malloc(dz->buflen * sizeof(float))) == NULL) {
  1338. sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
  1339. return(PROGRAM_ERROR);
  1340. }
  1341. dz->buflen /= bufchunks;
  1342. dz->sampbuf[0] = dz->bigbuf;
  1343. dz->sampbuf[1] = dz->sampbuf[0] + (dz->buflen * dz->infile->channels);
  1344. dz->sampbuf[2] = dz->sampbuf[1] + (dz->buflen * dz->otherfile->channels);
  1345. return(FINISHED);
  1346. }
  1347. /**************************** RING_MODULATE *************************/
  1348. int ring_modulate(dataptr dz)
  1349. {
  1350. int exit_status;
  1351. double sr = (double)dz->infile->srate;
  1352. int chans = dz->infile->channels;
  1353. double thistime = 0.0;
  1354. double this_pitch = 0.0, next_pitch, pitchstep = 0.0, thisfrq, tabstep, tabindex = 0.0, sinval;
  1355. double tabconvertor = (double)RM_SINTABSIZE/sr;
  1356. float *ibuf = dz->sampbuf[0];
  1357. int blokcnt = 0;
  1358. long m,k,j,r;
  1359. long total_stereosamp_cnt = 0;
  1360. if(dz->brksize[RM_FRQ]) {
  1361. if((exit_status = read_value_from_brktable(thistime,RM_FRQ,dz))<0)
  1362. return(exit_status);
  1363. }
  1364. next_pitch = log10(dz->param[RM_FRQ]);
  1365. while(dz->samps_left > 0) {
  1366. if((exit_status = read_samps(ibuf,dz))<0)
  1367. return(exit_status);
  1368. dz->ssampsread /= chans;
  1369. for(m=0,k=0;m<dz->ssampsread;m++,k+=chans) {
  1370. if(blokcnt<=0) {
  1371. total_stereosamp_cnt += RING_MOD_BLOK;
  1372. thistime = (double)total_stereosamp_cnt/sr; /* reading 1 block ahead */
  1373. if(dz->brksize[RM_FRQ]) {
  1374. if((exit_status = read_value_from_brktable(thistime,RM_FRQ,dz))<0)
  1375. return(exit_status);
  1376. }
  1377. this_pitch = next_pitch;
  1378. next_pitch = log10(dz->param[RM_FRQ]);
  1379. pitchstep = (next_pitch - this_pitch)/(double)RING_MOD_BLOK;
  1380. blokcnt = RING_MOD_BLOK;
  1381. }
  1382. blokcnt--;
  1383. thisfrq = pow(10.0,this_pitch);
  1384. tabstep = thisfrq * tabconvertor;
  1385. sinval = read_rmod_tab(tabindex,dz);
  1386. for(j=0;j<chans;j++) {
  1387. r = k+j;
  1388. ibuf[r] = (float)/*round*/((double)ibuf[r] * sinval);
  1389. }
  1390. tabindex += tabstep;
  1391. while(tabindex >= (double)RM_SINTABSIZE)
  1392. tabindex -= (double)RM_SINTABSIZE;
  1393. this_pitch += pitchstep;
  1394. }
  1395. if(dz->ssampsread > 0) {
  1396. if((exit_status = write_exact_samps(ibuf,dz->ssampsread * chans,dz))<0)
  1397. return(exit_status);
  1398. }
  1399. }
  1400. return(FINISHED);
  1401. }
  1402. /**************************** CROSS_MODULATE *************************/
  1403. int cross_modulate(dataptr dz)
  1404. {
  1405. int exit_status;
  1406. /*double sr = (double)dz->infile->srate;*/
  1407. float *ibuf1 = dz->sampbuf[0];
  1408. float *ibuf2 = dz->sampbuf[1];
  1409. float *obuf = dz->sampbuf[2];
  1410. int chans1 = dz->infile->channels;
  1411. int chans2 = dz->otherfile->channels;
  1412. int maxchans = max(chans1,chans2);
  1413. int samps_read, samps_read1, samps_read2, samps_to_write;
  1414. int m,k,j,r;
  1415. dz->tempsize = max(dz->insams[0],dz->insams[1]);
  1416. display_virtual_time(0L,dz);
  1417. for(;;) {
  1418. if((samps_read1 = fgetfbufEx(ibuf1,dz->buflen * chans1,dz->ifd[0],0))<0) {
  1419. sprintf(errstr,"Failed to read sound from 1st file.\n");
  1420. return(SYSTEM_ERROR);
  1421. }
  1422. if((samps_read2 = fgetfbufEx(ibuf2,dz->buflen * chans2,dz->ifd[1],0))<0) {
  1423. sprintf(errstr,"Failed to read sound from 2nd file.\n");
  1424. return(SYSTEM_ERROR);
  1425. }
  1426. if((samps_read = min(samps_read1/chans1,samps_read2/chans2))<=0)
  1427. break;
  1428. samps_to_write = samps_read * maxchans;
  1429. dz->ssampsread = samps_read;
  1430. for(m=0;m<dz->ssampsread;m++) {
  1431. switch(chans1) {
  1432. case(STEREO): // STEREO-STEREO
  1433. switch(chans2) {
  1434. case(STEREO):
  1435. k = m * 2;
  1436. for(j=0;j<STEREO;j++) {
  1437. r = k+j;
  1438. obuf[r] = (float)(ibuf1[r] * ibuf2[r]);
  1439. }
  1440. break;
  1441. case(MONO): // STEREO-MONO
  1442. k = m * 2;
  1443. for(j=0;j<STEREO;j++) {
  1444. r = k+j;
  1445. obuf[r] = (float)(ibuf1[r] * ibuf2[m]);
  1446. }
  1447. break;
  1448. }
  1449. break;
  1450. case(MONO): // MONO-MULTICHANNEL
  1451. k = m * chans2;
  1452. for(j=0;j<chans2;j++) {
  1453. r = k+j;
  1454. obuf[r] = (float)(ibuf1[m] * ibuf2[r]);
  1455. }
  1456. break;
  1457. default:
  1458. switch(chans2) { // MULTICHANNEL-MONO
  1459. case(MONO):
  1460. k = m * chans1;
  1461. for(j=0;j<chans1;j++) {
  1462. r = k+j;
  1463. obuf[r] = (float)(ibuf1[r] * ibuf2[m]);
  1464. }
  1465. break;
  1466. default: // MULTICHANNEL-MULTICHANNEL
  1467. obuf[m] = (float)(ibuf1[m] * ibuf2[m]);
  1468. break;
  1469. } // OTHER POSSIBLE CHANNEL COMBOS ARE TRAPPED EARLIER
  1470. }
  1471. }
  1472. if(samps_to_write==dz->buflen * maxchans) {
  1473. if((exit_status = write_exact_samps(obuf,samps_to_write,dz))<0)
  1474. return(exit_status);
  1475. } else if(samps_to_write > 0) {
  1476. if((exit_status = write_samps(obuf,samps_to_write,dz))<0)
  1477. return(exit_status);
  1478. }
  1479. }
  1480. dz->infile->channels = maxchans;
  1481. return(FINISHED);
  1482. }
  1483. /**************************** READ_RMOD_TAB *************************/
  1484. double read_rmod_tab(double dtabindex,dataptr dz)
  1485. {
  1486. double *sintab = dz->parray[RM_SINTAB];
  1487. int tabindex = (int)dtabindex; /* TRUNCATE */
  1488. double frac = dtabindex - (double)tabindex;
  1489. double loval = sintab[tabindex];
  1490. double hival = sintab[tabindex+1];
  1491. double incr = (hival - loval) * frac;
  1492. return(loval + incr);
  1493. }
  1494. /********************** CREATE_RM_SINTAB *************************/
  1495. int create_rm_sintab(dataptr dz)
  1496. {
  1497. int n;
  1498. double *sintab, sinsize = (double) RM_SINTABSIZE;
  1499. #ifdef NOTDEF
  1500. double scaling = (double)MAXSHORT/(double)(MAXSHORT+2); /* avoid clipping inverted max -ve sample */
  1501. #endif
  1502. if((dz->parray[RM_SINTAB] = (double *)malloc((RM_SINTABSIZE+1) * sizeof(double)))==NULL) {
  1503. sprintf(errstr,"INSUFFICIENT MEMORY for sine rtable.\n");
  1504. return(MEMORY_ERROR);
  1505. }
  1506. sintab = dz->parray[RM_SINTAB];
  1507. for(n=0;n<RM_SINTABSIZE;n++)
  1508. sintab[n] = sin(TWOPI * (double)n/sinsize) /* * scaling*/;
  1509. sintab[n] = 0.0;
  1510. return(FINISHED);
  1511. }
  1512. //TW UPDATE: NEW FUNCTIONS BELOW (converted to flotsams)
  1513. /********************** STACK_PREPROCESS *************************/
  1514. int stack_preprocess(dataptr dz)
  1515. {
  1516. int n, k;
  1517. double step, sum, thisstep, mult;
  1518. if(dz->itemcnt == 0) { /* value NOT in file */
  1519. if((dz->parray[STACK_TRANS] =
  1520. (double *)realloc((char *)(dz->parray[STACK_TRANS]),dz->iparam[STACK_CNT] * sizeof(double)))==NULL) {
  1521. sprintf(errstr,"Insufficient memory for storing stack transpositions.\n");
  1522. return(MEMORY_ERROR);
  1523. }
  1524. thisstep = 1.0;
  1525. mult = dz->parray[STACK_TRANS][0];
  1526. if(mult > 1.0) {
  1527. for(n=0;n<dz->iparam[STACK_CNT];n++) {
  1528. dz->parray[STACK_TRANS][n] = thisstep;
  1529. thisstep *= mult;
  1530. }
  1531. } else {
  1532. for(n=dz->iparam[STACK_CNT] - 1;n>=0;n--) { /* pitch highest track always at top */
  1533. dz->parray[STACK_TRANS][n] = thisstep;
  1534. thisstep *= mult;
  1535. }
  1536. }
  1537. dz->itemcnt = dz->iparam[STACK_CNT];
  1538. } else if(dz->itemcnt != dz->iparam[STACK_CNT]) {
  1539. fprintf(stdout,"WARNING: Count of transposition values in file (%d)\n",dz->itemcnt);
  1540. fprintf(stdout,"WARNING: does not correspond to number of stack components entered as parameter (%d),\n",dz->iparam[STACK_CNT]);
  1541. fprintf(stdout,"WARNING: Using %d as number of transpositions\n",dz->itemcnt);
  1542. fflush(stdout);
  1543. dz->iparam[STACK_CNT] = dz->itemcnt;
  1544. }
  1545. if((dz->parray[STACK_AMP] = (double *)malloc(dz->iparam[STACK_CNT] * sizeof(double)))==NULL) {
  1546. sprintf(errstr,"Insufficient memory for storing stack amplitudes.\n");
  1547. return(MEMORY_ERROR);
  1548. }
  1549. dz->param[STACK_MINTRANS] = HUGE;
  1550. for(n=0;n<dz->iparam[STACK_CNT];n++)
  1551. dz->param[STACK_MINTRANS] = min(dz->param[STACK_MINTRANS],dz->parray[STACK_TRANS][n]);
  1552. dz->param[STACK_DUR] = (double)round(dz->param[STACK_DUR] * 10)/10.0;
  1553. if(flteq(dz->param[STACK_DUR],1.0))
  1554. dz->iparam[STACK_DUR] = 0;
  1555. else if(flteq(dz->param[STACK_DUR],0.0)) {
  1556. sprintf(errstr,"You have asked to make NONE of the output!!");
  1557. return(USER_ERROR);
  1558. } else {
  1559. dz->param[STACK_DUR] /= dz->param[STACK_MINTRANS];
  1560. dz->iparam[STACK_DUR] = round(dz->param[STACK_DUR] * (dz->insams[0]/dz->infile->channels)) * dz->infile->channels;
  1561. }
  1562. /* attack distance from start, in input, in grouped-samples */
  1563. dz->iparam[STACK_OFFSET] = (long)round(dz->param[STACK_OFFSET] * dz->infile->srate);
  1564. /* attack distance from start, in output of slowest transposition, in grouped-samples */
  1565. if(dz->param[STACK_MINTRANS] < 1.0)
  1566. dz->iparam[STACK_OFFSET] = (long)round(dz->iparam[STACK_OFFSET] * (1.0/dz->param[STACK_MINTRANS]));
  1567. k = dz->iparam[STACK_CNT] - 1;
  1568. if(flteq(dz->param[STACK_LEAN],1.0)) {
  1569. for(n=0;n<dz->iparam[STACK_CNT];n++)
  1570. dz->parray[STACK_AMP][n] = dz->param[STACK_GAIN]/dz->iparam[STACK_CNT];
  1571. } else {
  1572. dz->parray[STACK_AMP][0] = dz->param[STACK_LEAN];
  1573. dz->parray[STACK_AMP][k] = 1.0;
  1574. step = dz->parray[STACK_AMP][k] - dz->parray[STACK_AMP][0];
  1575. step /= (double)k;
  1576. for(n = 1; n < k; n++)
  1577. dz->parray[STACK_AMP][n] = dz->parray[STACK_AMP][n-1] + step;
  1578. sum = 0.0;
  1579. for(n = 0; n < dz->iparam[STACK_CNT]; n++)
  1580. sum += dz->parray[STACK_AMP][n];
  1581. for(n = 0; n < dz->iparam[STACK_CNT]; n++) {
  1582. dz->parray[STACK_AMP][n] /= sum;
  1583. dz->parray[STACK_AMP][n] *= dz->param[STACK_GAIN];
  1584. if(dz->vflag[STACK_SEE]) {
  1585. fprintf(stdout,"INFO: stackitem[%d] level %lf\n",n,dz->parray[STACK_AMP][n]);
  1586. }
  1587. }
  1588. if(dz->vflag[STACK_SEE])
  1589. fflush(stdout);
  1590. }
  1591. return(FINISHED);
  1592. }
  1593. /********************** DO_STACK *************************/
  1594. int do_stack(dataptr dz)
  1595. {
  1596. int exit_status;
  1597. //TW ADDED FOR MULTICHANNEL WORK
  1598. int qq;
  1599. float *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
  1600. int chans = dz->infile->channels;
  1601. int bufsamplen = dz->buflen/chans; /* buffer length in grouped-samples */
  1602. int all_transpositions_active, n, nn, lastpos, *obufpos, max_obufpos;
  1603. double *inbufpos, maxoutsamp;
  1604. int *active_transpos;
  1605. float *lastibufval;
  1606. int *obufskip, *seeklen, *origseeklen, *offset, *eof_in_ibuf;
  1607. if(dz->iparam[STACK_DUR] <= 0)
  1608. dz->tempsize = (int)round(dz->insams[0] * (1.0/dz->param[STACK_MINTRANS]));
  1609. else
  1610. dz->tempsize = dz->iparam[STACK_DUR];
  1611. if((inbufpos = (double *)malloc(dz->iparam[STACK_CNT] * sizeof(double)))==NULL) {
  1612. sprintf(errstr,"Insufficient memory for storing input buffer pointers.\n");
  1613. return(MEMORY_ERROR);
  1614. }
  1615. if((obufpos = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1616. sprintf(errstr,"Insufficient memory for storing output buffer pointers.\n");
  1617. return(MEMORY_ERROR);
  1618. }
  1619. if((active_transpos = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1620. sprintf(errstr,"Insufficient memory for storing transposition flags.\n");
  1621. return(MEMORY_ERROR);
  1622. }
  1623. if((obufskip = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1624. sprintf(errstr,"Insufficient memory for storing seek values.\n");
  1625. return(MEMORY_ERROR);
  1626. }
  1627. if((lastibufval = (float *)malloc(dz->iparam[STACK_CNT] * sizeof(float) * dz->infile->channels))==NULL) {
  1628. sprintf(errstr,"Insufficient memory for storing last values in input bufs values.\n");
  1629. return(MEMORY_ERROR);
  1630. }
  1631. if((seeklen = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1632. sprintf(errstr,"Insufficient memory for storing seek values.\n");
  1633. return(MEMORY_ERROR);
  1634. }
  1635. if((origseeklen = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1636. sprintf(errstr,"Insufficient memory for storing original seek values.\n");
  1637. return(MEMORY_ERROR);
  1638. }
  1639. if((offset = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1640. sprintf(errstr,"Insufficient memory for storing offset values.\n");
  1641. return(MEMORY_ERROR);
  1642. }
  1643. if((eof_in_ibuf = (int *)malloc(dz->iparam[STACK_CNT] * sizeof(int)))==NULL) {
  1644. sprintf(errstr,"Insufficient memory for storing end-of-file markers.\n");
  1645. return(MEMORY_ERROR);
  1646. }
  1647. all_transpositions_active = 0;
  1648. for(n=0;n<dz->iparam[STACK_CNT];n++) {
  1649. all_transpositions_active |= (int) pow(2.0,n); /* set all bitflags for active buffers */
  1650. seeklen[n] = origseeklen[n] = 0;
  1651. inbufpos[n] = 0.0;
  1652. obufskip[n] = get_obuf_sampoffset(n,dz);
  1653. eof_in_ibuf[n] = dz->insams[0];
  1654. lastibufval[n] = 0.0f;
  1655. active_transpos[n] = 1;
  1656. }
  1657. if(chans > 1) {
  1658. while(n < dz->iparam[STACK_CNT] * chans)
  1659. lastibufval[n++] = 0.0f;
  1660. }
  1661. if(dz->vflag[1]) {
  1662. /* GET MAX OUTPUT LEVEL, THEN ADJUST LATER */
  1663. if(sloom) {
  1664. fprintf(stdout,"INFO: Assessing Output Level.\n");
  1665. fflush(stdout);
  1666. }
  1667. maxoutsamp = 0.0;
  1668. do {
  1669. memset((char *)obuf,0,dz->buflen * sizeof(float)); /* clear the output buffer */
  1670. max_obufpos = 0; /* clear count of outsamps written */
  1671. for(n=0;n<dz->iparam[STACK_CNT];n++) { /* For each transposition */
  1672. if(!active_transpos[n]) /* if this transposition inactive, go to next transpos */
  1673. continue;
  1674. if(obufskip[n] >= dz->buflen) { /* if more samps to skip than space in obuf */
  1675. obufskip[n] -= dz->buflen; /* decrement skip-value, ready for next outbuf, & go to next transpos */
  1676. continue;
  1677. } /* get the current seek position for this transposition */
  1678. sndseekEx(dz->ifd[0],seeklen[n],0); /* go to current buffer in infile, for this transposition */
  1679. obufpos[n] = obufskip[n]; /* set pointer to start in outputbuf for this write */
  1680. /* THIS LOOP READS INPUT AND WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
  1681. do {
  1682. memset((char *)ibuf,0,dz->buflen * sizeof(float)); /* clear the input buffer */
  1683. if((exit_status = read_samps(ibuf,dz)) < 0) {
  1684. sprintf(errstr,"Failed to read from input file.\n");
  1685. return(PROGRAM_ERROR);
  1686. }
  1687. /* THIS LOOP WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
  1688. do {
  1689. if((exit_status = transpos_and_add_to_obuf(n,&(obufpos[n]),&(inbufpos[n]),lastibufval,chans,dz)) < 0)
  1690. return(exit_status);
  1691. if(inbufpos[n] > (double)eof_in_ibuf[n]) {
  1692. active_transpos[n] = 0; /* break at end of input FILE */
  1693. break;
  1694. }
  1695. if (inbufpos[n] > bufsamplen - 1) { /* break at end of input BUFFER */
  1696. inbufpos[n] -= (double)bufsamplen; /* move ibufpointer to buf start */
  1697. lastpos = dz->buflen - chans; /* get last position in current buffer */
  1698. // MODIFY FOR MULTICHANNEL WORK
  1699. for(qq=0;qq<chans;qq++)
  1700. lastibufval[n+(dz->iparam[STACK_CNT] * qq)] = ibuf[lastpos++];
  1701. seeklen[n] += dz->buflen; /* set seek position for next read, in case */
  1702. /* we (later) break out during a WRITE-end */
  1703. if((eof_in_ibuf[n] -= dz->buflen) <= dz->buflen) /* if EOF is in the next buffer */
  1704. eof_in_ibuf[n] /= chans; /* convert to a grouped-sample count */
  1705. break; /* break from here and READ MORE INFILE */
  1706. }
  1707. } while(obufpos[n] < dz->buflen); /* break at end of OUTPUT BUFFER */
  1708. } while(active_transpos[n] && (obufpos[n] < dz->buflen)); /* if inFILE or outBUF finished, break from loop */
  1709. max_obufpos = max(max_obufpos,obufpos[n]);
  1710. obufskip[n] = 0; /* written outbuf we skipped into, so NO skip next time */
  1711. if(!active_transpos[n]) /* if FILE finished, reset flag for outer loop */
  1712. all_transpositions_active &= ~((int) pow(2.0,n));
  1713. }
  1714. if(max_obufpos > 0) {
  1715. if(dz->iparam[STACK_DUR] > 0) {
  1716. if(dz->total_samps_written + max_obufpos >= dz->iparam[STACK_DUR]) {
  1717. max_obufpos = dz->iparam[STACK_DUR] - dz->total_samps_written;
  1718. all_transpositions_active = 0;
  1719. }
  1720. }
  1721. for(nn = 0; nn < max_obufpos; nn++) {
  1722. if(fabs(obuf[nn]) > maxoutsamp)
  1723. maxoutsamp = fabs(obuf[nn]);
  1724. }
  1725. }
  1726. } while(all_transpositions_active);
  1727. if(flteq(maxoutsamp,0.0)) {
  1728. sprintf(errstr,"NO SIGNIFICANT SIGNAL LEVEL GENERATED\n");
  1729. return(DATA_ERROR);
  1730. }
  1731. for(n = 0; n < dz->iparam[STACK_CNT]; n++)
  1732. dz->parray[STACK_AMP][n] *= (0.95/maxoutsamp);
  1733. all_transpositions_active = 0;
  1734. for(n=0;n<dz->iparam[STACK_CNT];n++) {
  1735. all_transpositions_active |= (int)pow(2.0,n); /* set all bitflags for active buffers */
  1736. seeklen[n] = origseeklen[n] = 0;
  1737. inbufpos[n] = 0.0;
  1738. obufskip[n] = get_obuf_sampoffset(n,dz);
  1739. eof_in_ibuf[n] = dz->insams[0];
  1740. lastibufval[n] = 0.0f;
  1741. active_transpos[n] = 1;
  1742. }
  1743. if(chans > 1) {
  1744. while(n < dz->iparam[STACK_CNT] * chans)
  1745. lastibufval[n++] = 0.0f;
  1746. }
  1747. if(sloom) {
  1748. fprintf(stdout,"INFO: Generating Output.\n");
  1749. fflush(stdout);
  1750. }
  1751. }
  1752. /* THIS LOOP REPEATS UNTIL ALL INPUT TRANSPOSITION PROCESSES ARE COMPLETED */
  1753. do {
  1754. memset((char *)obuf,0,dz->buflen * sizeof(float)); /* clear the output buffer */
  1755. max_obufpos = 0; /* clear count of outsamps written */
  1756. for(n=0;n<dz->iparam[STACK_CNT];n++) { /* For each transposition */
  1757. if(!active_transpos[n]) /* if this transposition inactive, go to next transpos */
  1758. continue;
  1759. if(obufskip[n] >= dz->buflen) { /* if more samps to skip than space in obuf */
  1760. obufskip[n] -= dz->buflen; /* decrement skip-value, ready for next outbuf, & go to next transpos */
  1761. continue;
  1762. } /* get the current seek position for this transposition */
  1763. sndseekEx(dz->ifd[0],seeklen[n],0); /* go to current buffer in infile, for this transposition */
  1764. obufpos[n] = obufskip[n]; /* set pointer to start in outputbuf for this write */
  1765. /* THIS LOOP READS INPUT AND WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
  1766. do {
  1767. memset((char *)ibuf,0,dz->buflen * sizeof(float)); /* clear the input buffer */
  1768. if((exit_status = read_samps(ibuf,dz)) < 0) {
  1769. sprintf(errstr,"Failed to read from input file.\n");
  1770. return(PROGRAM_ERROR);
  1771. }
  1772. /* THIS LOOP WRITES OUTPUT UNTIL outbuf FULL OR inbuf OR infile EXHAUSTED */
  1773. do {
  1774. if((exit_status = transpos_and_add_to_obuf(n,&(obufpos[n]),&(inbufpos[n]),lastibufval,chans,dz)) < 0)
  1775. return(exit_status);
  1776. if(inbufpos[n] > (double)eof_in_ibuf[n]) {
  1777. active_transpos[n] = 0; /* break at end of input FILE */
  1778. break;
  1779. }
  1780. if (inbufpos[n] > bufsamplen - 1) { /* break at end of input BUFFER */
  1781. inbufpos[n] -= (double)bufsamplen; /* move ibufpointer to buf start */
  1782. lastpos = dz->buflen - chans; /* get last position in current buffer */
  1783. // MODIFY FOR MULTICHANNEL WORK
  1784. for(qq=0;qq<chans;qq++)
  1785. lastibufval[n+(dz->iparam[STACK_CNT] * qq)] = ibuf[lastpos++];
  1786. seeklen[n] += dz->buflen; /* set seek position for next read, in case */
  1787. /* we (later) break out during a WRITE-end */
  1788. if((eof_in_ibuf[n] -= dz->buflen) <= dz->buflen) /* if EOF is in the next buffer */
  1789. eof_in_ibuf[n] /= chans; /* convert to a grouped-sample count */
  1790. break; /* break from here and READ MORE INFILE */
  1791. }
  1792. } while(obufpos[n] < dz->buflen); /* break at end of OUTPUT BUFFER */
  1793. } while(active_transpos[n] && (obufpos[n] < dz->buflen)); /* if inFILE or outBUF finished, break from loop */
  1794. max_obufpos = max(max_obufpos,obufpos[n]);
  1795. obufskip[n] = 0; /* written outbuf we skipped into, so NO skip next time */
  1796. if(!active_transpos[n]) /* if FILE finished, reset flag for outer loop */
  1797. all_transpositions_active &= ~((int)pow(2.0,n));
  1798. }
  1799. if(max_obufpos > 0) {
  1800. if(dz->iparam[STACK_DUR] > 0) {
  1801. if(dz->total_samps_written + max_obufpos >= dz->iparam[STACK_DUR]) {
  1802. max_obufpos = dz->iparam[STACK_DUR] - dz->total_samps_written;
  1803. all_transpositions_active = 0;
  1804. }
  1805. }
  1806. if((exit_status = write_samps(obuf,max_obufpos,dz))<0)
  1807. return(exit_status);
  1808. }
  1809. } while(all_transpositions_active);
  1810. return(FINISHED);
  1811. }
  1812. /********************** GET_OBUF_SAMPOFFSET *************************/
  1813. int get_obuf_sampoffset(int n,dataptr dz)
  1814. {
  1815. double speed_ratio_vs_slowest, offset_frac;
  1816. int skip;
  1817. speed_ratio_vs_slowest = dz->parray[STACK_TRANS][n]/dz->param[STACK_MINTRANS];
  1818. if(flteq(speed_ratio_vs_slowest,1.0))
  1819. return 0;
  1820. offset_frac = 1.0 - (1.0/speed_ratio_vs_slowest);
  1821. skip = (int)round(dz->iparam[STACK_OFFSET] * offset_frac);
  1822. return (skip * dz->infile->channels);
  1823. }
  1824. /********************** TRANSPOS_AND_ADD_TO_OBUF *************************/
  1825. //TW new version for multichannel work !!
  1826. int transpos_and_add_to_obuf(int n,int *obufpos,double *inbufpos,float *lastival,int chans,dataptr dz)
  1827. {
  1828. float lastval, nextval, *ibuf = dz->sampbuf[0], *obuf = dz->sampbuf[1];
  1829. int i_bufpos, o_bufpos = *obufpos, i_bufpos_base = 0;
  1830. int k;
  1831. double step, val;
  1832. if(*inbufpos < -1.0) {
  1833. sprintf(errstr,"Impossible input buffer position encountered\n");
  1834. return(PROGRAM_ERROR);
  1835. }
  1836. if(*inbufpos < 0.0) /* ibuf pointer points between lastval in last buffer and 1st in this buffer */
  1837. step = 1.0 + (*inbufpos); /* interp position between these */
  1838. else {
  1839. step = fmod(*inbufpos,1.0);
  1840. i_bufpos_base = (int)floor(*inbufpos) * chans;
  1841. }
  1842. for(k=0;k<chans;k++) {
  1843. if(*inbufpos < 0.0) { /* ibuf pointer points between lastval in last buffer and 1st in this buffer */
  1844. i_bufpos = k; /* point to channel at start of this buffer */
  1845. lastval = lastival[n + (k * dz->iparam[STACK_CNT])]; /* get channel-val from end of last bufer */
  1846. nextval = ibuf[i_bufpos];
  1847. } else {
  1848. i_bufpos = i_bufpos_base + k;
  1849. lastval = ibuf[i_bufpos];
  1850. nextval = ibuf[i_bufpos+chans];
  1851. } /* add interpd val to val already in outbuf */
  1852. val = lastval + ((nextval - lastval) * step);
  1853. val *= dz->parray[STACK_AMP][n]; /* scaling by amplitude scalers */
  1854. obuf[o_bufpos] = (float)(obuf[o_bufpos] + val);
  1855. o_bufpos++;
  1856. }
  1857. *obufpos = o_bufpos; /* advance normally in outbuf */
  1858. *inbufpos += dz->parray[STACK_TRANS][n]; /* advance ibuf-pointer by transpos value */
  1859. return(FINISHED);
  1860. }