texture5.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627
  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> /*RWD*/
  25. #include <structures.h>
  26. #include <tkglobals.h>
  27. #include <globcon.h>
  28. #include <processno.h>
  29. #include <modeno.h>
  30. #include <arrays.h>
  31. #include <texture.h>
  32. #include <cdpmain.h>
  33. #include <sfsys.h>
  34. #ifdef _DEBUG
  35. #include <assert.h>
  36. #endif
  37. //#if defined unix || defined __GNUC__
  38. #define round(x) lround((x))
  39. //#endif
  40. static int setup_splice(int st_splicecnt,double **splicebuf);
  41. static int generate_origdur_and_frq(double **origdur,double **origfrq,dataptr dz);
  42. static int init_soundout_set(sndoutptr *sndout);
  43. static int replace_tset_by_soundout_set(noteptr thisnote,sndoutptr *sndout,
  44. double *origdur,double *origfrq,double mindur,int st_splicecnt,dataptr dz);
  45. static int convert_tsetnote_to_sndout_item(noteptr thisnote,sndoutptr sndout,
  46. double *origdur,double *origfrq,double mindur,int st_splicecnt,int *warning_set,dataptr dz);
  47. static int generate_previous_sndout(sndoutptr *sndout);
  48. static int get_thisdur(double *thisdur,noteptr thisnote,int thisins,
  49. double *origdur,double inv_trnsp,double mindur,dataptr dz);
  50. static int get_stereospace_compensation(double position,double *compensate);
  51. static int do_mix(sndoutptr sndout,double *splicebuf,dataptr dz);
  52. static int check_sequencing(sndoutptr sndout);
  53. static int add_samples_to_outbuf_from_inbuf(int *out_of_insamples,int * max_samp_written,
  54. sndoutptr sndout,double *splicebuf,int splicelen,/*int*/float *lbuf,dataptr dz);
  55. static void unlink_sndoutptr_at_start_of_list(sndoutptr sndout);
  56. static void unlink_sndoutptr(sndoutptr sndout);
  57. static double get_interpd_value(unsigned int here,double ibufpos,sndoutptr sndout);
  58. static int free_first_sndout(sndoutptr *sndout);
  59. //TW UPDATE 2002: to make texture from stereo sources (updated to flotsams)
  60. static int add_stereo_samples_to_outbuf_from_inbuf
  61. (int *out_of_insamples,int *max_samp_written,sndoutptr sndout,double *splicebuf,int splicelen,float *lbuffer,dataptr dz);
  62. static double get_interpd_value_stereo(unsigned int here,double ibufpos,double *chanval2,sndoutptr sndout);
  63. /**************************** PRODUCE_TEXTURE_SOUND *****************************/
  64. int produce_texture_sound(dataptr dz)
  65. {
  66. int exit_status;
  67. /*insamptr *insound = dz->tex->insnd;*/
  68. motifptr tset = dz->tex->timeset;
  69. sndoutptr sndout;
  70. noteptr thisnote = tset->firstnote;
  71. double *origdur, *origfrq, *splicebuf;
  72. double mindur = (dz->frametime + TEXTURE_SAFETY) * MS_TO_SECS;
  73. int st_splicecnt = round((dz->frametime * MS_TO_SECS) * dz->infile->srate);
  74. #ifdef MINDUR_OVERRIDE
  75. mindur = 0.0;
  76. st_splicecnt = 0;
  77. #endif
  78. if((exit_status = setup_splice(st_splicecnt,&splicebuf))<0)
  79. return(exit_status);
  80. if((exit_status = generate_origdur_and_frq(&origdur,&origfrq,dz))<0)
  81. return(exit_status);
  82. if((exit_status = init_soundout_set(&sndout))<0)
  83. return(exit_status);
  84. if((exit_status = replace_tset_by_soundout_set(thisnote,&sndout,origdur,origfrq,mindur,st_splicecnt,dz))<0)
  85. return(exit_status);
  86. free(origdur);
  87. free(origfrq);
  88. return do_mix(sndout,splicebuf,dz);
  89. }
  90. /************************** SETUP_SPLICE ************************/
  91. int setup_splice(int st_splicecnt,double **splicebuf)
  92. {
  93. int n, m;
  94. if((*splicebuf = (double *)malloc(st_splicecnt * sizeof(double)))==NULL) {
  95. sprintf(errstr,"INSUFFICIENT MEMORY for splice buffer.\n");
  96. return(MEMORY_ERROR);
  97. }
  98. for(m=0,n=st_splicecnt-1; n>=0; n--,m++)
  99. (*splicebuf)[m] = (double)n/(double)st_splicecnt;
  100. return(FINISHED);
  101. }
  102. /************************** GENERATE_ORIGDUR_AND_FRQ ************************/
  103. int generate_origdur_and_frq(double **origdur,double **origfrq,dataptr dz)
  104. {
  105. int n;
  106. if((*origdur = (double *)malloc(dz->infilecnt * sizeof(double)))==NULL) {
  107. sprintf(errstr,"INSUFFICIENT MEMORY to store original durations.\n");
  108. return(MEMORY_ERROR);
  109. }
  110. if((*origfrq = (double *)malloc(dz->infilecnt * sizeof(double)))==NULL) {
  111. sprintf(errstr,"INSUFFICIENT MEMORY to store original frqs.\n");
  112. return(MEMORY_ERROR);
  113. }
  114. for(n=0;n <dz->infilecnt;n++) {
  115. //TW UPDATE: Now allowing stereo sources to be used to make texture
  116. (*origdur)[n] = (double)dz->insams[n]/(double)dz->infile->channels/(double)dz->infile->srate;
  117. (*origfrq)[n] = miditohz(((dz->tex->insnd)[n])->pitch);
  118. }
  119. return(FINISHED);
  120. }
  121. /************************** INIT_SOUNDOUT_SET ************************/
  122. int init_soundout_set(sndoutptr *sndout)
  123. {
  124. if((*sndout = (sndoutptr)malloc(sizeof(struct soundout)))==NULL) {
  125. sprintf(errstr,"INSUFFICIENT MEMORY for soundout pointers.\n");
  126. return(MEMORY_ERROR);
  127. }
  128. (*sndout)->last = (sndoutptr)0;
  129. (*sndout)->next = (sndoutptr)0;
  130. return(FINISHED);
  131. }
  132. /************************** REPLACE_TSET_BY_SOUNDOUT_SET ************************/
  133. int replace_tset_by_soundout_set
  134. (noteptr thisnote,sndoutptr *sndout,double *origdur,double *origfrq,double mindur,int st_splicecnt,dataptr dz)
  135. {
  136. int exit_status;
  137. int warning_set = FALSE;
  138. while((thisnote->next)!=(noteptr)0) /* go to end of tset */
  139. thisnote = thisnote->next;
  140. while(thisnote!=(noteptr)0) {
  141. if((exit_status = convert_tsetnote_to_sndout_item
  142. (thisnote,*sndout,origdur,origfrq,mindur,st_splicecnt,&warning_set,dz))<0)
  143. return(exit_status);
  144. if((exit_status = generate_previous_sndout(sndout))<0)
  145. return(exit_status);
  146. if(thisnote->last!=NULL) {
  147. thisnote = thisnote->last; /* free tset from end backwards */
  148. free(thisnote->next);
  149. } else {
  150. free(thisnote);
  151. if((exit_status = free_first_sndout(sndout))<0)
  152. return(exit_status);
  153. thisnote = NULL;
  154. }
  155. }
  156. return(FINISHED);
  157. }
  158. /************************** CONVERT_TSETNOTE_TO_SNDOUT_ITEM ************************/
  159. //TW "STEREO" defined in globcon.h
  160. #define MAXGAIN (1.0)
  161. int convert_tsetnote_to_sndout_item
  162. (noteptr thisnote,sndoutptr sndout,double *origdur,double *origfrq,double mindur,int st_splicecnt,int *warning_set,dataptr dz)
  163. {
  164. int exit_status;
  165. int thisins;
  166. unsigned int insampcnt, st_osampcnt;
  167. double indur;
  168. double thisfrq,thisdur,trnspstep,inv_trnsp,thisamp,thispos,compensate;
  169. thisins = thisnote->instr;
  170. thisfrq = miditohz((double)thisnote->pitch);
  171. trnspstep = thisfrq/origfrq[thisins];
  172. inv_trnsp = 1.0/trnspstep;
  173. if((exit_status = get_thisdur(&thisdur,thisnote,thisins,origdur,inv_trnsp,mindur,dz))<0)
  174. return(exit_status);
  175. indur = thisdur * trnspstep;
  176. //TW UPDATE now counting either mono samples or pairs-of-stereo-sample pairs (as with st_osampcnt) as possibly using stereo input
  177. insampcnt = min(dz->insams[thisins]/dz->infile->channels,round(indur * (double)dz->infile->srate));
  178. st_osampcnt = round((double)insampcnt * inv_trnsp);
  179. if(st_osampcnt <= (unsigned int)st_splicecnt) {
  180. sprintf(errstr,"Error in samplecount calculations: convert_tsetnote_to_sndout_item()\n");
  181. return(PROGRAM_ERROR);
  182. }
  183. thisamp = thisnote->amp/(double)MIDITOP;
  184. thispos = thisnote->spacepos;
  185. if((exit_status = get_stereospace_compensation(thispos,&compensate))<0)
  186. return(exit_status);
  187. if(thisamp > MAXGAIN) {
  188. #ifdef _DEBUG
  189. assert(thisamp <= MAXGAIN);
  190. #endif
  191. if(!(*warning_set)) {
  192. fprintf(stdout,"WARNING: one or more events exceed max level. Adjusted.\n");
  193. fflush(stdout);
  194. *warning_set = TRUE;
  195. }
  196. thisamp = MAXGAIN;
  197. }
  198. sndout->inbuf = ((dz->tex->insnd)[thisins])->buffer;
  199. sndout->ibufcnt = insampcnt;
  200. sndout->st_sstttime = round(thisnote->ntime * dz->infile->srate);
  201. sndout->st_sendtime = sndout->st_sstttime + st_osampcnt; /* Redundant variable: might need if func revised */
  202. sndout->st_splicpos = sndout->st_sendtime - st_splicecnt;
  203. sndout->ibufpos = 0.0;
  204. sndout->step = trnspstep;
  205. //TW UPDATE: in stereo-input case, only 1 gain value used, as no spatialisation takes place
  206. if(dz->infile->channels==STEREO) {
  207. sndout->lgain = thisamp;
  208. } else {
  209. sndout->lgain = thisamp * (1.0 - thispos) * compensate;
  210. sndout->rgain = thisamp * thispos * compensate;
  211. }
  212. return(FINISHED);
  213. }
  214. /************************** GENERATE_PREVIOUS_SNDOUT ************************/
  215. int generate_previous_sndout(sndoutptr *sndout)
  216. {
  217. sndoutptr new;
  218. if((new = (sndoutptr)malloc(sizeof(struct soundout)))==NULL) {
  219. sprintf(errstr,"INSUFFICIENT MEMORY for new soundout pointers.\n");
  220. return(MEMORY_ERROR);
  221. }
  222. new->last = (sndoutptr)0;
  223. new->next = *sndout;
  224. (*sndout)->last = new;
  225. *sndout = new;
  226. return(FINISHED);
  227. }
  228. /************************** FREE_FIRST_SNDOUT ************************/
  229. int free_first_sndout(sndoutptr *sndout)
  230. {
  231. if((*sndout = (*sndout)->next)==NULL) {
  232. sprintf(errstr,"Problem in free_first_sndout()\n");
  233. return(PROGRAM_ERROR);
  234. }
  235. free((*sndout)->last);
  236. (*sndout)->last = NULL;
  237. return(FINISHED);
  238. }
  239. /************************** GET_THISDUR ************************/
  240. int get_thisdur
  241. (double *thisdur,noteptr thisnote,int thisins,double *origdur,double inv_trnsp,double mindur,dataptr dz)
  242. {
  243. double transposed_dur = origdur[thisins] * inv_trnsp;
  244. *thisdur = thisnote->dur;
  245. if(*thisdur>transposed_dur)
  246. *thisdur = transposed_dur;
  247. else if(dz->vflag[TEX_IGNORE_DUR])
  248. *thisdur = transposed_dur;
  249. if(*thisdur<mindur) {
  250. sprintf(errstr,
  251. "too short dur generated (%lf : mindur = %lf): get_thisdur()\n",*thisdur,mindur);
  252. return(PROGRAM_ERROR);
  253. }
  254. return(FINISHED);
  255. }
  256. /************************** GET_STEREOSPACE_COMPENSATION ************************
  257. *
  258. * 1) comp(ensation) is a factor which compensates for the apparent
  259. * loss of perceived amplitude as a sound moves out of the absolute
  260. * left or absolute right position (sound from a single loudspeaker)
  261. * by simple linear interpolation.
  262. * At first we define comp to vary LINERALY from 0.0 at L or R,
  263. * to 1.0 in centre.
  264. * 2) NONLIN makes this varation nonlinear, but smooth at the centre, and
  265. * still between 0.0 and 1.0
  266. * 3) As a signal of fixed perceived level moves from left to right (or v.v.)
  267. * we wish to boost the amplitude from each loudspeaker somewhat,
  268. * using a curve of the shape now defined.
  269. * The maximum possible amplitude is 1.0. To define how much we should
  270. * boost amplitude at any point on the L-R axis, we need to define
  271. * a ratio (MAXBOOST) with which to multiply the signal.
  272. * Multiplying comp-curve by this, defines a curve of amplitude-boosting values.
  273. * 4) 1.0 is now added to this curve, to give a multiplier of amplitude at
  274. * each point along the left-right axis.
  275. * And MAXBOOST is subtracted, so that the level
  276. * from each loudspeaker when at maximum boost cannot exceed
  277. * MAXGAIN (1.0).
  278. */
  279. #define NONLIN (0.5)
  280. #define MAXBOOST (0.25)
  281. int get_stereospace_compensation(double position,double *compensate)
  282. {
  283. double comp = 1.0 - (fabs((position * (double)2.0) - (double)1.0)); /* 9a */
  284. comp = pow(comp,NONLIN); /* 9b */
  285. comp *= MAXBOOST; /* 9c */
  286. comp += (1.0 - MAXBOOST); /* 9d */
  287. *compensate = comp;
  288. return(FINISHED);
  289. }
  290. /************************** DO_MIX ************************
  291. *
  292. * 1) Position, in stereo-samples, of start-of-splice in this-sndout-struct =
  293. * sndout->st_splicpos
  294. * Position in actual-samples of ditto =
  295. * sndout->st_splicpos * STEREO
  296. * Position relative to start of current buffer =
  297. * (sndout->st_splicpos * STEREO) - (obufcnt * dz->buflen);
  298. * Same position expressed relative to start-of-splice (so that value 0 = start_of_splice) =
  299. * -((sndout->st_splicpos * STEREO) - (obufcnt * dz->buflen));
  300. */
  301. int do_mix(sndoutptr sndout,double *splicebuf,dataptr dz)
  302. {
  303. int exit_status;
  304. int out_of_insamples;
  305. /*unsigned int totaltime = 0;*/
  306. int max_samp_written, n;
  307. unsigned long this_sampend, obufcnt = 0;
  308. long splicelen = round((dz->frametime * MS_TO_SECS) * dz->infile->srate) * STEREO;
  309. sndoutptr startsnd = sndout, endsnd = sndout;
  310. /*int*/float *lbuf;
  311. //TW UPDATE handles stereo input files
  312. int is_stereo = 0;
  313. #ifdef MINDUR_OVERRIDE
  314. splicelen = 0;
  315. #endif
  316. if(dz->infile->channels == STEREO)
  317. is_stereo = 1;
  318. //TW MOVED from texprepro
  319. dz->infile->channels = STEREO; /* for output time calculations */
  320. if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
  321. return(exit_status);
  322. if((lbuf = (float *)malloc(dz->buflen * sizeof(float)))==NULL) {
  323. sprintf(errstr,"INSUFFICIENT MEMORY for mixing buffers.\n");
  324. return(MEMORY_ERROR);
  325. }
  326. dz->sbufptr[0] = dz->sampbuf[0];
  327. /* <--SAFETY CHECK */
  328. if((exit_status = check_sequencing(sndout))<0)
  329. return(exit_status);
  330. /* SAFETY CHECK--> */
  331. while(startsnd != NULL) { /* until we reach end of event list */
  332. this_sampend = (obufcnt+1) * dz->buflen; /* get absolute samplecnt of end of current buf */
  333. /* look for NEW events starting during this outbuf */
  334. if(sndout!=NULL) {
  335. while(sndout->st_sstttime * STEREO < this_sampend) {
  336. sndout->obufpos = (sndout->st_sstttime * STEREO) % dz->buflen;/* obufptr for new event */
  337. sndout->st_splicpos = (sndout->st_splicpos * STEREO)-(obufcnt * dz->buflen);/* NOTE1 abv*/
  338. sndout->st_splicpos = -(sndout->st_splicpos); /* NOTE 1 above */
  339. sndout = sndout->next;
  340. endsnd = sndout; /* update the endmarker of the active events list */
  341. if(endsnd == NULL) /* if all events finished,break */
  342. break;
  343. }
  344. }
  345. sndout = startsnd; /* set start to 1st event still active */
  346. memset((char *)lbuf,0,dz->buflen * sizeof(float)); /* empty output buffer */
  347. if(sndout == endsnd) { /* If there are NO active events during this buffer */
  348. if(endsnd != NULL) /* and we are not at end of event list */
  349. max_samp_written = dz->buflen; /* setup to write an empty buffer */
  350. else {
  351. sprintf(errstr,"Error in loop logic: do_mix()\n");
  352. return(PROGRAM_ERROR);
  353. }
  354. } else
  355. max_samp_written = 0;
  356. while(sndout!= endsnd) { /* look in all active buffers */
  357. out_of_insamples = FALSE;
  358. //TW UPDATE: handles stereo input
  359. if(is_stereo) {
  360. if((exit_status = add_stereo_samples_to_outbuf_from_inbuf
  361. (&out_of_insamples,&max_samp_written,sndout,splicebuf,splicelen,lbuf,dz))<0)
  362. return(exit_status);
  363. } else {
  364. if((exit_status = add_samples_to_outbuf_from_inbuf
  365. (&out_of_insamples,&max_samp_written,sndout,splicebuf,splicelen,lbuf,dz))<0)
  366. return(exit_status);
  367. }
  368. if(out_of_insamples) { /* if inbuf exhausted for THIS event */
  369. if(sndout->next==NULL) { /* if at end of list */
  370. if(sndout->last==NULL) { /* if this is definitively the last active event */
  371. free(sndout); /* free it */
  372. startsnd = NULL; /* and set ptr to NULL, so we dropout of outerloop */
  373. break;
  374. } else { /* BUT if some previous event still active */
  375. sndout = sndout->last; /* unlink final event from list */
  376. free(sndout->next);
  377. sndout->next = NULL;
  378. sndout = sndout->next; /* move sndout to end of list */
  379. }
  380. } else if(sndout==startsnd) { /* if this is 1st active event in list */
  381. sndout = sndout->next; /* proceed to next event */
  382. startsnd = sndout; /* move start of active list to this next event */
  383. unlink_sndoutptr_at_start_of_list(sndout->last);
  384. } else { /* else if this is NOT 1st active event in list */
  385. sndout = sndout->next; /* proceed to next event */
  386. unlink_sndoutptr(sndout->last);/* unlink the exhausted event from (active) list */
  387. }
  388. } else { /* else there is data remaining in inbuf for THIS event */
  389. sndout->obufpos = 0; /* so reset obufpos to start of next obuf */
  390. sndout->st_splicpos += dz->buflen;/* reset relativeposition splice-start & nextbufstart */
  391. sndout = sndout->next; /* and proceed to next event */
  392. }
  393. }
  394. if(startsnd!=NULL) /* If we're not at the end of ALL events, write a full buffer */
  395. max_samp_written = dz->buflen;
  396. for(n=0;n<max_samp_written;n++)
  397. dz->sampbuf[0][n] = lbuf[n];
  398. if(max_samp_written > 0) {
  399. if((exit_status = write_samps(dz->sampbuf[0],max_samp_written,dz))<0)
  400. return(exit_status);
  401. }
  402. obufcnt++;
  403. }
  404. /*if(dz->iparam[TEX_MAXOUT] > MAXSAMP) {*/
  405. if(dz->param[TEX_MAXOUT] > F_MAXSAMP) {
  406. fprintf(stdout,"WARNING: OVERLOAD: suggest attenuation by < %lf\n",
  407. //TW UPDATE (need to factor in the attenation already being used to give correct new attenuation)
  408. (((double)F_MAXSAMP/(double)dz->param[TEX_MAXOUT])) * dz->param[TEXTURE_ATTEN]);
  409. fflush(stdout);
  410. }
  411. return(FINISHED);
  412. }
  413. /************************** CHECK_SEQUENCING ************************/
  414. int check_sequencing(sndoutptr sndout)
  415. {
  416. unsigned int lasttime = sndout->st_sstttime;
  417. unsigned int thistime;
  418. while(sndout->next != (sndoutptr)0) {
  419. sndout = sndout->next;
  420. if((thistime = sndout->st_sstttime) < lasttime) {
  421. sprintf(errstr,"Sequencing anomaly in sndout list: check_sequencing()\n");
  422. return(PROGRAM_ERROR);
  423. }
  424. lasttime = thistime;
  425. }
  426. return(FINISHED);
  427. }
  428. /************************** ADD_SAMPLES_TO_OUTBUF_FROM_INBUF ************************/
  429. int add_samples_to_outbuf_from_inbuf
  430. (int *out_of_insamples,int *max_samp_written,sndoutptr sndout,double *splicebuf,int splicelen,float *lbuffer,dataptr dz)
  431. {
  432. unsigned int thisopos = sndout->obufpos;
  433. unsigned int here;
  434. double hereval = 0.0;
  435. float *lbuf = lbuffer + thisopos;
  436. float *lbufend = lbuffer + dz->buflen;
  437. int splicpos = sndout->st_splicpos + thisopos;
  438. float outval, thismaxoutval;
  439. int max_set = FALSE;
  440. while(lbuf < lbufend) {
  441. if((here = (unsigned int) sndout->ibufpos) >= sndout->ibufcnt) { /* TRUNCATE : get current pos in inbuf */
  442. *out_of_insamples = TRUE;
  443. *max_samp_written = max(*max_samp_written,lbuf - lbuffer);
  444. /* SAFETY CHECK--> */
  445. if(splicpos < splicelen) {
  446. sprintf(errstr,"BUM endsplice: add_samples_to_outbuf_from_inbuf()\n");
  447. return(PROGRAM_ERROR);
  448. }
  449. /* <--SAFETY CHECK */
  450. max_set = TRUE;
  451. break;
  452. }
  453. hereval = get_interpd_value(here,sndout->ibufpos,sndout);
  454. /* SAFETY FOR ARITHMETIC ROUNDING ERROS CALCULATING START OF SPLICE --> */
  455. if(splicpos >= splicelen)
  456. hereval = 0.0;
  457. /* <--SAFETY */
  458. if(splicpos >= 0)
  459. hereval *= splicebuf[splicpos >> 1];
  460. splicpos += STEREO;
  461. outval =(float)( *lbuf + (hereval * sndout->lgain ));
  462. if((thismaxoutval = (float) fabs(outval)) > dz->param[TEX_MAXOUT])
  463. dz->param[TEX_MAXOUT] = thismaxoutval;
  464. *lbuf = outval;
  465. lbuf++;
  466. outval = (float)(*lbuf + (hereval * sndout->rgain));
  467. if((thismaxoutval = (float) fabs(outval)) > dz->param[TEX_MAXOUT])
  468. dz->param[TEX_MAXOUT] = thismaxoutval;
  469. *lbuf = outval;
  470. lbuf++;
  471. sndout->ibufpos += sndout->step;
  472. }
  473. if(!max_set)
  474. *max_samp_written = dz->buflen;
  475. return(FINISHED);
  476. }
  477. //TW UPDATE: NEW FUNCTIONfor stereo input (updated for flotsams)
  478. /************************** ADD_STEREO_SAMPLES_TO_OUTBUF_FROM_INBUF ************************/
  479. int add_stereo_samples_to_outbuf_from_inbuf
  480. (int *out_of_insamples,int *max_samp_written,sndoutptr sndout,double *splicebuf,int splicelen,float *lbuffer,dataptr dz)
  481. {
  482. unsigned int thisopos = sndout->obufpos;
  483. unsigned int here;
  484. double chanval1, chanval2;
  485. float *lbuf = lbuffer + thisopos;
  486. float *lbufend = lbuffer + dz->buflen;
  487. int splicpos = sndout->st_splicpos + thisopos;
  488. float outval, thismaxoutval;
  489. int max_set = FALSE;
  490. while(lbuf < lbufend) {
  491. if((here = (unsigned int)sndout->ibufpos)>=sndout->ibufcnt) { /* TRUNCATE : get current pos in inbuf */
  492. *out_of_insamples = TRUE;
  493. *max_samp_written = max(*max_samp_written,lbuf - lbuffer);
  494. if(splicpos < splicelen) {
  495. sprintf(errstr,"BUM endsplice: add_samples_to_outbuf_from_inbuf()\n");
  496. return(PROGRAM_ERROR);
  497. }
  498. max_set = TRUE;
  499. break;
  500. }
  501. chanval1 = get_interpd_value_stereo(here,sndout->ibufpos,&chanval2,sndout);
  502. /* SAFETY FOR ARITHMETIC ROUNDING ERROS CALCULATING START OF SPLICE --> */
  503. if(splicpos >= splicelen) {
  504. chanval1 = 0.0;
  505. chanval2 = 0.0;
  506. }
  507. /* <--SAFETY */
  508. if(splicpos >= 0) {
  509. chanval1 *= splicebuf[splicpos >> 1];
  510. chanval2 *= splicebuf[splicpos >> 1];
  511. }
  512. splicpos += STEREO;
  513. outval = (float)(*lbuf + (chanval1 * sndout->lgain));
  514. if((thismaxoutval = (float)fabs(outval))>dz->param[TEX_MAXOUT])
  515. dz->param[TEX_MAXOUT] = thismaxoutval;
  516. *lbuf = outval;
  517. lbuf++;
  518. outval = (float)(*lbuf + (chanval2 * sndout->lgain)); /* only one gain val for stereo inputs: kept in lgain */
  519. if((thismaxoutval = (float)fabs(outval))>dz->param[TEX_MAXOUT])
  520. dz->param[TEX_MAXOUT] = thismaxoutval;
  521. *lbuf = outval;
  522. lbuf++;
  523. sndout->ibufpos += sndout->step;
  524. }
  525. if(!max_set)
  526. *max_samp_written = dz->buflen;
  527. return(FINISHED);
  528. }
  529. /************************** GET_INTERPD_VALUE ************************/
  530. double get_interpd_value(unsigned int here,double ibufpos,sndoutptr sndout)
  531. {
  532. unsigned int next = here+1; /* NB all inbufs have a wraparound (0val) point at end */
  533. double frac = ibufpos - (double)here;
  534. double hereval = (double)(sndout->inbuf[here]);
  535. double nextval = (double)(sndout->inbuf[next]);
  536. double diff = nextval - hereval;
  537. diff *= frac;
  538. return(hereval+diff);
  539. }
  540. //TW UPDATE NEW FUNCTION for stereo input
  541. /************************** GET_INTERPD_VALUE_STEREO ************************/
  542. double get_interpd_value_stereo(unsigned int here,double ibufpos,double *chanval2,sndoutptr sndout)
  543. {
  544. unsigned int next = here+1; /* NB all inbufs have a wraparound (0val) point at end */
  545. double frac = ibufpos - (double)here;
  546. double hereval, nextval, diff;
  547. double chanval1;
  548. unsigned int sthere = here * 2, stnext = next * 2;
  549. hereval = (double)(sndout->inbuf[sthere]);
  550. nextval = (double)(sndout->inbuf[stnext]);
  551. diff = (nextval - hereval) * frac;
  552. chanval1 = hereval+diff;
  553. sthere++;
  554. stnext++;
  555. hereval = (double)(sndout->inbuf[sthere]);
  556. nextval = (double)(sndout->inbuf[stnext]);
  557. diff = (nextval - hereval) * frac;
  558. *chanval2 = hereval+diff;
  559. return(chanval1);
  560. }
  561. /************************** UNLINK_SNDOUTPTR_AT_START_OF_LIST ************************/
  562. void unlink_sndoutptr_at_start_of_list(sndoutptr sndout)
  563. {
  564. sndout->next->last = (sndoutptr)0;
  565. free(sndout);
  566. }
  567. /************************** UNLINK_SNDOUTPTR ************************/
  568. void unlink_sndoutptr(sndoutptr sndout)
  569. {
  570. sndout->next->last = sndout->last;
  571. sndout->last->next = sndout->next;
  572. free(sndout);
  573. }