pluck.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  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 <string.h>
  25. #include <structures.h>
  26. #include <tkglobals.h>
  27. #include <globcon.h>
  28. #include <processno.h>
  29. #include <modeno.h>
  30. #include <arrays.h>
  31. #include <filetype.h>
  32. #include <envel.h>
  33. #include <cdpmain.h>
  34. #include <sfsys.h>
  35. #include <osbind.h>
  36. //#ifdef unix
  37. #define round(x) lround((x))
  38. //#endif
  39. static int do_wrap(int samps_to_wrap,dataptr dz);
  40. static int read_rest_of_file(int initial_bufsize,dataptr dz);
  41. static int pluck(dataptr dz);
  42. static int envsyn_env(int *phase,int cyclestart,int *cycle_end,double one_less_trof,dataptr dz);
  43. static int envsyn_troffed(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz);
  44. static int envsyn_userdef(int cyclestart,int *cyclend,int *phase,dataptr dz);
  45. static int envsyn_rising( int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz);
  46. static int envsyn_falling(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz);
  47. static double do_firsthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz);
  48. static double do_lasthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz);
  49. static double do_rising(int k,int cyclelen,double one_less_trof,dataptr dz);
  50. static double do_falling(int k,int cyclelen,double one_less_trof,dataptr dz);
  51. static int read_from_user_envelope(double *env_val,double table_index,int init,dataptr dz);
  52. /****************************** ENVELOPE_PLUCK *************************/
  53. int envelope_pluck(dataptr dz)
  54. {
  55. int exit_status;
  56. int initial_bufsize;
  57. int first_read_offset = dz->sampbuf[PLK_INITBUF] - dz->bigbuf;
  58. dz->buflen -= first_read_offset; /* size of buffer from where first read takes place */
  59. if((exit_status = read_samps(dz->sampbuf[PLK_INITBUF],dz))<0)
  60. return(exit_status);
  61. initial_bufsize = dz->buflen;
  62. if((exit_status = pluck(dz))<0)
  63. return(exit_status);
  64. dz->buflen = dz->iparam[ENV_PLK_OBUFLEN]; /* size of buffer for subsequent reads */
  65. return read_rest_of_file(initial_bufsize,dz);
  66. }
  67. /**************************** PLUCK ******************************
  68. *
  69. * (1) goalbufend is the last sample of the cycle in the input file buffer from which we will
  70. * derive the pluck attack. We read it backwards, from this LAST sample.
  71. * (2) The outplukptr points to the position in the output buffer where we
  72. * are WRITING pluck-form wavecycles. We write these BKWDS
  73. * from here to start of dz->sampbuf[PLK_OUTBUF].
  74. * (3) Set goalbufptr to start(i.e. end!!) of goalbuf.
  75. * (4) Inverse_index is a BACKWARDS count of the samples in the pluck.
  76. * (5) For each wavecycle of Pluck attack..
  77. * (6) For each sample in wavecycle....
  78. * (7) Noiselevel is directly proportional to distance (bkwds) into pluck.
  79. * (8) Then reduced via exponential curve.
  80. * (9) Becoming this fraction of the maximum amplitude.
  81. * (10) Noise input itself is a random value in range +- this noiselevel value.
  82. * (11) Reinitialise goalbufptr for eack wavecycle.
  83. * (13a)By the time we reach the start of the pluck, signal will cause#
  84. * spurious foldover when added to orig signal: but this will simply make
  85. * it more like noise!!
  86. * (12) Calculate sample length of initial risetime.
  87. * (13) Finally, envelope start of pluck!!
  88. */
  89. int pluck(dataptr dz)
  90. {
  91. int n, m, inverse_index;
  92. float *goalbufend, *goalbufptr, *outplukptr;
  93. double noise_level;
  94. /*int*/double thisnoise;
  95. int startup;
  96. int pluklen = dz->iparam[ENV_PLK_CYCLEN] * dz->iparam[ENV_PLK_WAVELEN];
  97. if((goalbufend = dz->sampbuf[PLK_PLUKEND] + dz->iparam[ENV_PLK_WAVELEN] - 1) >=dz->sampbuf[PLK_BUFEND]) {
  98. sprintf(errstr,"End of goal pluck_cycle falls outside buffer: Insufficient memory to proceed.\n");
  99. return(GOAL_FAILED); /* 1 */
  100. }
  101. if((outplukptr = dz->sampbuf[PLK_PLUKEND] - 1) < dz->bigbuf) { /* 2 */
  102. sprintf(errstr,"Buffer accounting problem.\n");
  103. return(PROGRAM_ERROR);
  104. }
  105. goalbufptr = goalbufend; /* 3 */
  106. inverse_index = 0; /* 4 */
  107. for(n=0;n<dz->iparam[ENV_PLK_CYCLEN];n++) { /* 5 */
  108. for(m=0;m<dz->iparam[ENV_PLK_WAVELEN];m++) { /* 6 */
  109. noise_level = (double)inverse_index/(double)pluklen; /* 7 */
  110. noise_level = pow(noise_level,dz->param[ENV_PLK_DECAY]); /* 8 */
  111. noise_level = noise_level * (double)F_MAXSAMP; /* 9 */
  112. thisnoise = /*round*/ (((drand48() * 2.0) - 1.0) * noise_level); /* 10 */
  113. *outplukptr = (float)((*goalbufptr) + thisnoise);
  114. outplukptr--;
  115. goalbufptr--;
  116. inverse_index++;
  117. }
  118. goalbufptr = goalbufend; /* 11 */
  119. }
  120. startup = round(ENV_PLK_ONSET_TIME * MS_TO_SECS * (double)dz->infile->srate); /* 12 */
  121. startup = min(startup,dz->iparam[ENV_PLK_CYCLEN] * dz->iparam[ENV_PLK_WAVELEN]);
  122. for(n=0;n<startup;n++) {
  123. outplukptr++; /* 13 */
  124. *outplukptr = (float) /*round */(*outplukptr * (double)n/(double)startup);
  125. }
  126. return(FINISHED);
  127. }
  128. /*********************** READ_REST_OF_FILE ************************
  129. *
  130. * (1) If the input buffer was NOT filled, then we must be at end of file: so write data and return.
  131. * (2) Samples to write is those read,
  132. * MINUS the length of initial replaced segment (dz->iparam[ENV_PLK-STSAMP])
  133. * PLUS the added initial segment (dz->iparam[ENV_PLK_OWRAPLEN]).
  134. * ELSE
  135. * (3) Write a standard buffer_full, from start of obuf_preflow (where pluck has been constructed).
  136. * (4) This leaves, [ENV_PLK_OWRAPLEN] samples in end of dz->sampbuf[PLK_OUTBUF],
  137. * SO samps_to_wrap = [ENV_PLK_OWRAPLEN];
  138. * (6) Do the wrap-around.
  139. * (8) Whilst ever there is something in wrap-around part of buffer...
  140. * (10) Try to read more samples (may get full-buff, part-buf
  141. * or zero if file already exhausted).
  142. * (11) Total samps to write is the wrapped samps plus those just read.
  143. * (12) If this leaves no samps to wrap (i.e. buffer is NOT full, therefore FILE must be exhausted),
  144. * write all these samps to out and quit.
  145. * (13) ELSE, write a bufferfull and do another wrap-around.
  146. */
  147. int read_rest_of_file(int initial_bufsize,dataptr dz)
  148. {
  149. int exit_status;
  150. int samps_to_write, samps_to_wrap;
  151. int pluklen = dz->iparam[ENV_PLK_CYCLEN] * dz->iparam[ENV_PLK_WAVELEN];
  152. if(dz->ssampsread < (int)(initial_bufsize)) { /* 1 */
  153. if((samps_to_write = dz->ssampsread - dz->iparam[ENV_PLK_ENDSAMP] + pluklen)>0) { /* 2 */
  154. if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],samps_to_write,dz))<0)
  155. return(exit_status);
  156. }
  157. } else {
  158. if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],dz->buflen,dz))<0) /* 3 */
  159. return(exit_status);
  160. samps_to_wrap = dz->iparam[ENV_PLK_OWRAPLEN]; /* 4 */
  161. if((exit_status = do_wrap(samps_to_wrap,dz))<0) /* 6 */
  162. return(exit_status);
  163. while(samps_to_wrap > 0) { /* 8 */
  164. if((exit_status = read_samps(dz->sampbuf[PLK_INBUF],dz))<0) /* 10 */
  165. return(exit_status);
  166. samps_to_write = samps_to_wrap + dz->ssampsread; /* 11 */
  167. if((samps_to_wrap = samps_to_write - dz->buflen) <= 0) { /* 12 */
  168. if(samps_to_write > 0) {
  169. if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],samps_to_write,dz))<0)
  170. return(exit_status);
  171. }
  172. } else {
  173. if((exit_status = write_samps(dz->sampbuf[PLK_OUTBUF],dz->buflen,dz))<0) /* 13 */
  174. return(exit_status);
  175. if((exit_status = do_wrap(samps_to_wrap,dz))<0)
  176. return(exit_status);
  177. }
  178. }
  179. }
  180. return(FINISHED);
  181. }
  182. /*********************** DO_WRAP ************************/
  183. int do_wrap(int samps_to_wrap,dataptr dz)
  184. {
  185. memmove((char *)dz->sampbuf[PLK_OUTBUF],(char *)dz->sampbuf[PLK_OBUFWRAP],(samps_to_wrap)*sizeof(float));
  186. return(FINISHED);
  187. }
  188. /************************** ENVSYN **************************/
  189. int envsyn(dataptr dz)
  190. {
  191. int exit_status;
  192. int current_pos = 0, cyclelen, cycle_end, done = 0;
  193. int phase, initial_phase;
  194. double thistime = 0.0, one_less_trof;
  195. int samps_needed;
  196. dz->param[ENVSYN_WSIZE] *= MS_TO_SECS;
  197. samps_needed = (int)floor((dz->param[ENVSYN_DUR]/ dz->param[ENVSYN_WSIZE]) + 1);
  198. dz->tempsize = samps_needed * sizeof(float);
  199. if((exit_status = read_values_from_all_existing_brktables(thistime,dz)) < 0)
  200. return(exit_status);
  201. one_less_trof = 1.0 - dz->param[ENVSYN_TROF];
  202. cyclelen = (int)round(dz->param[ENVSYN_CYCLEN]/dz->param[ENVSYN_WSIZE]);
  203. cycle_end = cyclelen;
  204. phase = (int)round((double)cyclelen * dz->param[ENVSYN_STARTPHASE]);
  205. initial_phase = phase;
  206. for (;;) {
  207. if(cyclelen < 2) {
  208. sprintf(errstr,"ENVELOPE DURATION TOO SHORT FOR WINDOWSIZE at time %lf\n",
  209. (dz->total_samps_written + current_pos) * dz->param[ENV_WSIZE]);
  210. return(DATA_ERROR);
  211. }
  212. if((exit_status = envsyn_env(&phase,current_pos,&cycle_end,one_less_trof,dz))< 0)
  213. return(exit_status);
  214. if((done += cyclelen) >= samps_needed + initial_phase)
  215. break;
  216. thistime += dz->param[ENVSYN_CYCLEN];
  217. if((exit_status = read_values_from_all_existing_brktables(thistime,dz)) < 0)
  218. return(exit_status);
  219. one_less_trof = 1.0 - dz->param[ENVSYN_TROF];
  220. cyclelen = (int)round(dz->param[ENVSYN_CYCLEN]/dz->param[ENVSYN_WSIZE]);
  221. current_pos = cycle_end;
  222. cycle_end = current_pos + cyclelen;
  223. }
  224. if(cycle_end > 0) {
  225. if((exit_status = write_samps(dz->flbufptr[0],cycle_end,dz))<0)
  226. return(exit_status);
  227. }
  228. return(FINISHED);
  229. }
  230. /************************** ENVSYN_ENV **************************/
  231. int envsyn_env(int *phase,int cyclestart,int *cycle_end,double one_less_trof,dataptr dz)
  232. {
  233. switch(dz->mode) {
  234. case(ENVSYN_TROFFED): return envsyn_troffed(cyclestart,cycle_end,one_less_trof,phase,dz);
  235. case(ENVSYN_USERDEF): return envsyn_userdef(cyclestart,cycle_end,phase,dz);
  236. case(ENVSYN_RISING): return envsyn_rising(cyclestart,cycle_end,one_less_trof,phase,dz);
  237. case(ENVSYN_FALLING): return envsyn_falling(cyclestart,cycle_end,one_less_trof,phase,dz);
  238. default:
  239. sprintf(errstr,"Unknown case: envsyn_env()\n");
  240. return(PROGRAM_ERROR);
  241. }
  242. return(CONTINUE);
  243. }
  244. /************************** ENVSYN_TROFFED *******************************/
  245. int envsyn_troffed(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz)
  246. {
  247. int exit_status;
  248. register int k = 0, j = cyclestart;
  249. int cyclelen = *cyclend - cyclestart;
  250. int cyclehlf = cyclelen/2;
  251. int cyclemid = cyclestart + cyclehlf;
  252. float *b = dz->flbufptr[0];
  253. if(*phase > 0) {
  254. if(*phase >= cyclehlf) {
  255. cyclemid = -1;
  256. k = (*phase - cyclehlf);
  257. } else {
  258. cyclemid -= *phase;
  259. k = *phase;
  260. }
  261. (*cyclend) -= *phase;
  262. *phase = 0;
  263. }
  264. while(j<cyclemid) {
  265. b[j] = (float)do_firsthalf_trof(k,cyclehlf,one_less_trof,dz);
  266. k++;
  267. j++;
  268. if(j >= dz->buflen) {
  269. if((exit_status = write_samps(b,dz->buflen,dz))<0)
  270. return(exit_status);
  271. j = 0;
  272. *cyclend -= dz->buflen;
  273. }
  274. }
  275. if(cyclemid >= 0)
  276. k = 0;
  277. cyclehlf = cyclelen - cyclehlf;
  278. while(j < *cyclend) {
  279. b[j] = (float)do_lasthalf_trof(k,cyclehlf,one_less_trof,dz);
  280. k++;
  281. j++;
  282. if(j >= dz->buflen) {
  283. if((exit_status = write_samps(b,dz->buflen,dz))<0)
  284. return(exit_status);
  285. j = 0;
  286. *cyclend -= dz->buflen;
  287. }
  288. }
  289. return(FINISHED);
  290. }
  291. /*************************** ENVSYN_USERDEF ***************************/
  292. int envsyn_userdef(int cyclestart,int *cyclend,int *phase,dataptr dz)
  293. {
  294. int exit_status;
  295. register int k = 0, j = cyclestart;
  296. int cyclelen = *cyclend - cyclestart;
  297. double index;
  298. double z;
  299. int init = 1;
  300. float *b = dz->flbufptr[0];
  301. if(*phase > 0) {
  302. k = *phase;
  303. (*cyclend) -= *phase;
  304. *phase = 0;
  305. }
  306. while(j<*cyclend) {
  307. index = (double)k/(double)cyclelen;
  308. if((exit_status = read_from_user_envelope(&z,index,init,dz))<0)
  309. return(exit_status);
  310. b[j] = (float)z;
  311. k++;
  312. j++;
  313. if(j >= dz->buflen) {
  314. if((exit_status = write_samps(b,dz->buflen,dz))<0)
  315. return(exit_status);
  316. j = 0;
  317. *cyclend -= dz->buflen;
  318. }
  319. init = 0;
  320. }
  321. return(FINISHED);
  322. }
  323. /*************************** ENVSYN_RISING ***********************/
  324. int envsyn_rising(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz)
  325. {
  326. int exit_status;
  327. register int k = 0, j = cyclestart;
  328. int cyclelen = *cyclend - cyclestart;
  329. float *b = dz->flbufptr[0];
  330. if(*phase > 0) {
  331. k = *phase;
  332. (*cyclend) -= *phase;
  333. *phase = 0;
  334. }
  335. while(j<*cyclend) {
  336. b[j] = (float)do_rising(k,cyclelen - 1,one_less_trof,dz);
  337. k++;
  338. j++;
  339. if(j >= dz->buflen) {
  340. if((exit_status = write_samps(b,dz->buflen,dz))<0)
  341. return(exit_status);
  342. j = 0;
  343. *cyclend -= dz->buflen;
  344. }
  345. }
  346. return(FINISHED);
  347. }
  348. /********************** ENVSYN_FALLING *************************/
  349. int envsyn_falling(int cyclestart,int *cyclend,double one_less_trof,int *phase,dataptr dz)
  350. {
  351. int exit_status;
  352. register int k = 0, j = cyclestart;
  353. int cyclelen = *cyclend - cyclestart;
  354. float *b = dz->flbufptr[0];
  355. if(*phase > 0) {
  356. k = *phase;
  357. (*cyclend) -= *phase;
  358. *phase = 0;
  359. }
  360. while(j<*cyclend) {
  361. b[j] = (float)do_falling(k,cyclelen - 1,one_less_trof,dz);
  362. k++;
  363. j++;
  364. if(j >= dz->buflen) {
  365. if((exit_status = write_samps(b,dz->buflen,dz))<0)
  366. return(exit_status);
  367. j = 0;
  368. *cyclend -= dz->buflen;
  369. }
  370. }
  371. return(FINISHED);
  372. }
  373. /******************* DO_FIRSTHALF_TROF **************************/
  374. double do_firsthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz)
  375. {
  376. double z = 1.0 - ((double)k/(double)cyclehlf);
  377. z = (pow(z,dz->param[ENVSYN_EXPON]) * one_less_trof) + dz->param[ENVSYN_TROF];
  378. return (z);
  379. }
  380. /******************* DO_LASTHALF_TROF **************************/
  381. double do_lasthalf_trof(int k,int cyclehlf,double one_less_trof,dataptr dz)
  382. {
  383. double z = (double)k/(double)cyclehlf;
  384. z = (pow(z,dz->param[ENVSYN_EXPON]) * one_less_trof) + dz->param[ENVSYN_TROF];
  385. return(z);
  386. }
  387. /************************ DO_RISING_TROFFED *******************************/
  388. double do_rising(int k,int cyclelen,double one_less_trof,dataptr dz)
  389. {
  390. double z = (double)k/(double)cyclelen;
  391. z = pow(z,dz->param[ENVSYN_EXPON]);
  392. z *= one_less_trof;
  393. z += dz->param[ENVSYN_TROF];
  394. return(z);
  395. }
  396. /************************ DO_FALLING_TROFFED *******************************/
  397. double do_falling(int k,int cyclelen,double one_less_trof,dataptr dz)
  398. {
  399. double z;
  400. z = 1.0 - ((double)k/(double)cyclelen);
  401. z = (pow(z,dz->param[ENVSYN_EXPON]) * one_less_trof) + dz->param[ENVSYN_TROF];
  402. return z;
  403. }
  404. /************************ READ_FROM_USER_ENVELOPE *******************************/
  405. int read_from_user_envelope(double *env_val,double table_index,int init,dataptr dz)
  406. {
  407. double *p;
  408. double hi_env, lo_env, hi_index, lo_index;
  409. double env;
  410. if(init)
  411. dz->ptr[ENVSYN_ENV] = dz->parray[ENVSYN_ENV];
  412. p = dz->ptr[ENVSYN_ENV];
  413. while(table_index > *p) {
  414. if((p += 2) >= dz->ptr[ENVSYN_ENVEND]) {
  415. sprintf(errstr,"Problem reading user envelope data: read_from_user_envelope()\n");
  416. return(PROGRAM_ERROR);
  417. }
  418. }
  419. if(p != dz->parray[ENVSYN_ENV]) {
  420. hi_env = *(p+1);
  421. hi_index = *p;
  422. lo_env = *(p-1);
  423. lo_index = *(p-2);
  424. env = (double)((table_index - lo_index)/(hi_index - lo_index));
  425. env *= (double)(hi_env - lo_env);
  426. env += (double)lo_env;
  427. } else
  428. env = *(p+1);
  429. dz->ptr[ENVSYN_ENV] = p;
  430. *env_val = env;
  431. return(FINISHED);
  432. }