mixprepro.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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 <limits.h>
  25. #include <structures.h>
  26. #include <tkglobals.h>
  27. #include <globcon.h>
  28. #include <filetype.h>
  29. #include <modeno.h>
  30. #include <mix.h>
  31. #include <sfsys.h>
  32. //#ifdef unix
  33. #define round(x) lround((x))
  34. //#endif
  35. static int do_refill_acts(dataptr dz);
  36. static void sort_actions(dataptr dz);
  37. static int init_inbufs(dataptr dz);
  38. static int gen_mcr_table(dataptr dz);
  39. /************************** MIX_PREPROCESS ******************/
  40. int mix_preprocess(dataptr dz)
  41. {
  42. int exit_status;
  43. if((exit_status = do_refill_acts(dz))<0)
  44. return(exit_status);
  45. sort_actions(dz);
  46. if(dz->iparam[MIX_STRTPOS] > 0) /* Allow for mix not starting at zero time */
  47. dz->iparam[MIX_STRTPOS_IN_ACTION] = (int)max(dz->iparam[MIX_STRTPOS] - dz->act[0]->position,0L);
  48. /* NEW 2000 */
  49. /* RWD now in samps */
  50. dz->tempsize = (dz->act[dz->iparam[MIX_TOTAL_ACTCNT]-1]->position - dz->iparam[MIX_STRTPOS_IN_ACTION]);
  51. /* NEW 2000 */
  52. return init_inbufs(dz);
  53. }
  54. /*************************** DO_REFILL_ACTS **************************/
  55. int do_refill_acts(dataptr dz)
  56. {
  57. int n;
  58. int samps_used, actcnt = dz->iparam[MIX_TOTAL_ACTCNT];
  59. int arraysize = actcnt + BIGARRAY; /* Generate more space for further actions. */
  60. if((dz->act=(actptr *)realloc(dz->act,arraysize * sizeof(actptr)))==NULL) {
  61. sprintf(errstr,"INSUFFICIENT MEMORY to construct buffer-fill action pointers.\n");
  62. return(MEMORY_ERROR);
  63. }
  64. for(n=0;n<dz->iparam[MIX_TOTAL_ACTCNT];n+=2) { /* actions paired as ON/OFF, so we look only at ON bufs */
  65. if(dz->act[n]->val->samplen > dz->buflen) { /* If more data in (action's) file than fits in 1 buffer */
  66. samps_used = 0;
  67. while((samps_used += dz->buflen) < dz->act[n]->val->samplen) {
  68. if((dz->act[actcnt] = (actptr)malloc(sizeof(struct action)))==NULL) {
  69. sprintf(errstr,"INSUFFICIENT MEMORY to construct buffer-fill actions.\n");
  70. return(MEMORY_ERROR);
  71. }
  72. dz->act[actcnt]->val = dz->act[n]->val; /* Create a new action, using same vals as the original */
  73. dz->act[actcnt]->position = dz->act[n]->position + samps_used;/* Positioned 1 further buflen later, and */
  74. dz->act[actcnt]->role = MIX_ACTION_REFILL; /* with role REFILL */
  75. if(++actcnt >= arraysize) {
  76. arraysize += BIGARRAY;
  77. if((dz->act=(actptr *)realloc(dz->act,arraysize * sizeof(actptr)))==NULL) {
  78. sprintf(errstr,"INSUFFICIENT MEMORY to reallocate buffer-fill action pointers.\n");
  79. return(MEMORY_ERROR);
  80. }
  81. }
  82. }
  83. }
  84. }
  85. if((dz->act=(actptr *)realloc(dz->act,actcnt * sizeof(actptr)))==NULL) {
  86. sprintf(errstr,"INSUFFICIENT MEMORY to reallocate buffer-fill actions.\n");
  87. return(MEMORY_ERROR);
  88. }
  89. dz->iparam[MIX_TOTAL_ACTCNT] = (int)actcnt;
  90. return(FINISHED);
  91. }
  92. /************************* SORT_ACTIONS ****************************/
  93. void sort_actions(dataptr dz)
  94. {
  95. actptr temp;
  96. int n, m;
  97. for(n=0;n<dz->iparam[MIX_TOTAL_ACTCNT]-1;n++) {
  98. for(m=n+1;m<dz->iparam[MIX_TOTAL_ACTCNT];m++) {
  99. if(dz->act[m]->position < dz->act[n]->position) {
  100. temp = dz->act[n];
  101. dz->act[n] = dz->act[m];
  102. dz->act[m] = temp;
  103. }
  104. }
  105. }
  106. }
  107. /****************************** INIT_INBUFS *********************************
  108. *
  109. * (1) Create the space for buffers within each bufitem. NB enough space
  110. * for ALL these buffers must be allocated in the initial creation
  111. * of 'inbuf' in create_buffers.
  112. * (2) Create the pointers to point to start and current_position in ACTIVE bufs.
  113. */
  114. int init_inbufs(dataptr dz)
  115. {
  116. int n;
  117. float *thisbuf = dz->sampbuf[IBUFMIX];
  118. dz->buflist = (mixbufptr *)malloc(dz->bufcnt * sizeof(mixbufptr));
  119. for(n=0;n<dz->bufcnt;n++) {
  120. dz->buflist[n] = NULL;
  121. if((dz->buflist[n] = (mixbufptr)malloc(sizeof(struct bufitem)))==NULL) {
  122. sprintf(errstr,"INSUFFICIENT MEMORY for buffer list.\n");
  123. return(MEMORY_ERROR);
  124. }
  125. dz->buflist[n]->status = MIX_ACTION_OFF;
  126. dz->buflist[n]->buf = thisbuf;
  127. dz->buflist[n]->here = dz->buflist[n]->buf;
  128. thisbuf += dz->buflen;
  129. }
  130. if((dz->activebuf = (int *)malloc(dz->bufcnt * sizeof(int)))==NULL) {
  131. sprintf(errstr,"INSUFFICIENT MEMORY for active buffer list.\n");
  132. return(MEMORY_ERROR);
  133. }
  134. if((dz->activebuf_ptr = (float **)malloc(dz->bufcnt * sizeof(float *)))==NULL) {
  135. sprintf(errstr,"INSUFFICIENT MEMORY for active buffer pointer list.\n");
  136. return(MEMORY_ERROR);
  137. }
  138. return(FINISHED);
  139. }
  140. /****************************** MIXTWO_PREPROCESS ************************************/
  141. int mixtwo_preprocess(dataptr dz)
  142. {
  143. int shsecsize = F_SECSIZE * dz->infile->channels;
  144. double k;
  145. dz->iparam[MIX_STAGGER] = round(dz->param[MIX_STAGGER] * (double)dz->infile->srate) * dz->infile->channels;
  146. dz->iparam[MIX_STAGGER] = (dz->iparam[MIX_STAGGER]/shsecsize) * shsecsize;
  147. dz->iparam[MIX_STAGGER] = min(dz->iparam[MIX_STAGGER],dz->insams[0] - dz->infile->channels);
  148. dz->iparam[MIX_SKIP] = round(dz->param[MIX_SKIP] * (double)dz->infile->srate) * dz->infile->channels;
  149. dz->iparam[MIX_SKIP] = (dz->iparam[MIX_SKIP]/shsecsize) * shsecsize;
  150. dz->iparam[MIX_SKIP] = min(dz->iparam[MIX_SKIP],dz->insams[1] - dz->infile->channels);
  151. if(((k = (dz->param[MIX_STTA] * (double)dz->infile->srate)) * (double)dz->infile->channels) >= (double)LONG_MAX)
  152. dz->iparam[MIX_STTA] = INT_MAX;
  153. else
  154. dz->iparam[MIX_STTA] = round(dz->param[MIX_STTA] * (double)dz->infile->srate) * dz->infile->channels;
  155. dz->iparam[MIX_STTA] = (dz->iparam[MIX_STTA]/shsecsize) * shsecsize;
  156. dz->param[MIX2_GAIN1] = dz->param[MIX_SKEW]/(dz->param[MIX_SKEW] + 1.0);
  157. dz->param[MIX2_GAIN2] = 1.0 - dz->param[MIX2_GAIN1];
  158. if(((k = (dz->param[MIX_DURA] * (double)dz->infile->srate)) * (double)dz->infile->channels) >= (double)LONG_MAX)
  159. dz->iparam[MIX_DURA] = dz->insams[0] + dz->insams[1];
  160. else
  161. dz->iparam[MIX_DURA] = round(k) * dz->infile->channels;
  162. if(dz->iparam[MIX_DURA] <= dz->iparam[MIX_STAGGER]) {
  163. sprintf(errstr,"Mix cuts off before 2nd file enters\n");
  164. return(DATA_ERROR);
  165. }
  166. if(dz->iparam[MIX_STTA] >= dz->insams[0]) {
  167. sprintf(errstr,"Mix does not start until first file has ended.\n");
  168. return(DATA_ERROR);
  169. }
  170. if(dz->iparam[MIX_DURA] <= dz->iparam[MIX_STTA]) {
  171. sprintf(errstr,"Mix end is before mix start.\n");
  172. return(DATA_ERROR);
  173. }
  174. /* RWD all now in samps */
  175. dz->tempsize = max((dz->insams[1]-dz->iparam[MIX_SKIP]+dz->iparam[MIX_STAGGER]),dz->insams[0]);
  176. dz->tempsize = min(dz->tempsize,dz->iparam[MIX_DURA]);
  177. dz->tempsize -= (dz->iparam[MIX_STTA]);
  178. return(FINISHED);
  179. }
  180. /********************** MIXCROSS_PREPROCESS **********************/
  181. int mixcross_preprocess(dataptr dz)
  182. {
  183. int exit_status;
  184. int crosfact, maxend;
  185. /* CONVERT TO SAMPLES */
  186. dz->iparam[MCR_BEGIN] = round(dz->param[MCR_BEGIN] * dz->infile->srate) * dz->infile->channels;
  187. /* CONVERT TO SAMPLES AND APPROXIMATE TO SECTOR BOUNDARY */
  188. dz->iparam[MCR_STAGGER] = round(dz->param[MCR_STAGGER] * dz->infile->srate) * dz->infile->channels;
  189. //TW SAFE ??
  190. //#ifdef NOTDEF
  191. // dz->iparam[MCR_STAGGER] = (dz->iparam[MCR_STAGGER]/SECSIZE) * SECSIZE;
  192. //#endif
  193. maxend = min(dz->insams[0],dz->iparam[MCR_STAGGER] + dz->insams[1]);
  194. if(dz->param[MCR_END] > 0.0) { /* i.e. HAS BEEN SET */
  195. dz->iparam[MCR_END] = round(dz->param[MCR_END] * dz->infile->srate) * dz->infile->channels;
  196. dz->iparam[MCR_END] = min(dz->iparam[MCR_END],maxend); /* END may be curtailed by stagger's rounding */
  197. } else
  198. dz->iparam[MCR_END] = maxend;
  199. /* TEST CROSSFADE PARAMS FOR CONSISTENCY */
  200. if(dz->iparam[MCR_BEGIN] < dz->iparam[MCR_STAGGER]) {
  201. sprintf(errstr,"Crossfade begins before end of stagger: Impossible.\n");
  202. return(USER_ERROR);
  203. }
  204. if(dz->iparam[MCR_BEGIN] >= dz->iparam[MCR_STAGGER] + dz->insams[1]) {
  205. sprintf(errstr,"Crossfade begins after end of 2nd file: Impossible.\n");
  206. return(USER_ERROR);
  207. }
  208. if((crosfact = dz->iparam[MCR_END] - dz->iparam[MCR_BEGIN])<=0) {
  209. sprintf(errstr,"Crossfade length is zero or negative: Impossible.\n");
  210. return(USER_ERROR);
  211. }
  212. /* SET UP LENGTH OF CROSSFADE, AND THE DIVIDE FACTOR FOR INDEXING THIS */
  213. dz->param[MCR_CROSFACT] = 1.0/(double)crosfact;
  214. /* SET CONTOUR TYPE */
  215. if(dz->mode==MCLIN)
  216. dz->iparam[MCR_CONTOUR] = MCR_LINEAR;
  217. else if(flteq(dz->param[MCR_POWFAC],1.0))
  218. dz->iparam[MCR_CONTOUR] = MCR_COSIN;
  219. else
  220. dz->iparam[MCR_CONTOUR] = MCR_SKEWED;
  221. /* FOR COSIN CONTOUR TYPE : MAKE COSTABLE */
  222. if(dz->iparam[MCR_CONTOUR]==MCR_SKEWED || dz->iparam[MCR_CONTOUR]==MCR_COSIN) {
  223. if((exit_status = gen_mcr_table(dz))<0)
  224. return(exit_status);
  225. }
  226. /* SET CROSS-FADE INDEX OT ZERO */
  227. dz->iparam[MCR_INDEX] = 0;
  228. return(FINISHED);
  229. }
  230. /*** GONE TO TK *********************** GEN_MCR_TABLE **********************/
  231. int gen_mcr_table(dataptr dz)
  232. {
  233. int n;
  234. double *costable;
  235. if((dz->parray[MCR_COSTABLE] = (double *)malloc((MCR_TABLEN+1)* sizeof(double)))==NULL) {
  236. sprintf(errstr,"INSUFFICIENT MEMORY for cosine table.\n");
  237. return(MEMORY_ERROR);
  238. }
  239. costable = dz->parray[MCR_COSTABLE];
  240. for(n=0;n<MCR_TABLEN;n++) {
  241. costable[n] = ((double)n/(double)(MCR_TABLEN)) * PI;
  242. costable[n] = cos(costable[n]);
  243. costable[n] += 1.0;
  244. costable[n] /= 2.0;
  245. costable[n] = 1.0 - costable[n];
  246. costable[n] = max(0.0,costable[n]);
  247. costable[n] = min(costable[n],1.0);
  248. }
  249. costable[n] = 1.0;
  250. return(FINISHED);
  251. }
  252. /******************************** GET_INBETWEEN_RATIOS ***************************/
  253. int get_inbetween_ratios(dataptr dz)
  254. {
  255. double *p, scaler;
  256. int n;
  257. switch(dz->mode) {
  258. case(INBI_RATIO): /* now read as special data */
  259. break;
  260. case(INBI_COUNT): /* GENERATE RATIOS AUTOMATICALLY IN A NEWLY MALLOCD brkpnt TABLE */
  261. dz->iparam[INBETW] = round(dz->param[INBETW]);
  262. if((dz->brk[INBETW] = (double *)malloc(dz->iparam[INBETW] * sizeof(double)))==NULL) {
  263. sprintf(errstr,"INSUFFICIENT MEMORY for inbetween values store.\n");
  264. return(MEMORY_ERROR);
  265. }
  266. dz->no_brk[INBETW] = FALSE;
  267. p = dz->brk[INBETW];
  268. scaler = 1.0/(double)(dz->iparam[INBETW]+1);
  269. for(n=1;n<=dz->iparam[INBETW];n++)
  270. *p++ = (double)n * scaler;
  271. break;
  272. default:
  273. sprintf(errstr,"Unknown mode in get_inbetween_ratios()\n");
  274. return(PROGRAM_ERROR);
  275. }
  276. return(FINISHED);
  277. }
  278. /************** CHECK_NEW_FILENAME ***********/
  279. int check_new_filename(char *filename,dataptr dz)
  280. {
  281. int exit_status;
  282. double maxamp, maxloc;
  283. int maxrep;
  284. int getmax = 0, getmaxinfo = 0;
  285. infileptr ifp;
  286. if((ifp = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  287. sprintf(errstr,"INSUFFICIENT MEMORY to store data on files.\n");
  288. return(MEMORY_ERROR);
  289. }
  290. if(dz->mode!=MSH_DUPL_AND_RENAME || dz->vflag[MSH_NOCHECK])
  291. return(FINISHED);
  292. if(dz->infile->srate==0) {
  293. sprintf(errstr,"srate not set: check_new_filename()\n");
  294. return(PROGRAM_ERROR);
  295. }
  296. if(dz->ifd!=NULL) /* set up by default in main() */
  297. free(dz->ifd);
  298. if((exit_status = establish_file_data_storage_for_mix((int)1,dz))<0)
  299. return(exit_status);
  300. if((dz->ifd[0] = sndopenEx(filename,0,CDP_OPEN_RDONLY)) < 0) {
  301. sprintf(errstr,"Failed to open sndfile %s: check_new_filename()\n",filename);
  302. return(DATA_ERROR);
  303. }
  304. if((exit_status = readhead(ifp,dz->ifd[0],filename,&maxamp,&maxloc,&maxrep,getmax,getmaxinfo))<0)
  305. return(exit_status);
  306. copy_to_fileptr(ifp,dz->otherfile);
  307. if(dz->otherfile->filetype!=SNDFILE) {
  308. sprintf(errstr,"%s is not a soundfile: check_new_filename()\n",filename);
  309. return(DATA_ERROR);
  310. }
  311. if(dz->otherfile->srate != dz->infile->srate) {
  312. sprintf(errstr,"Incompatible srate: check_new_filename()\n");
  313. return(DATA_ERROR);
  314. }
  315. return(FINISHED);
  316. }