pvoc_addon.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. /*
  2. * Copyright (c) 1983-2020 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. /* RWD 22/02/2018 replaced hamming with vonhann window for smooth frame transition. */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <structures.h>
  25. #include <globcon.h>
  26. #include <tkglobals.h>
  27. #include <pnames.h>
  28. #include <processno.h>
  29. #include <modeno.h>
  30. #include <logic.h>
  31. #include <cdpmain.h>
  32. #include <pvoc.h>
  33. #include <string.h>
  34. #include <sfsys.h>
  35. #include <pvoc.h>
  36. static int outfloats(float *nextOut, float *maxsampl,float *minsample,int *num_overflows,int todo, dataptr dz);
  37. static int pvoc_float_array(int nnn,float **ptr);
  38. static int sndwrite_header(float R,dataptr dz);
  39. static void hamming(float *win,int winLen,int even);
  40. static void vonhann(float *win,int winLen,int even);
  41. static int pvoc_time_display(int nI,unsigned int samps_so_far,int srate,int *samptime,dataptr dz);
  42. static void reset_file_params_for_analout(int orig_proctype,int orig_srate,
  43. int orig_chans,int orig_stype,dataptr dz);
  44. /****************************** PVOC_OUT *************************
  45. *
  46. * 1) This code assumes there is an output analysis file from a previous process.
  47. * 2) It assumes that the NAME of that file (orig_outfilename) is NOT the name of the new file being created.
  48. * In fact its name have a HIGHER numeric index, so when it is deleted there are no gaps
  49. * in the numbering of VALID outfiles (which run from 0 upwards).
  50. * 3) root_outfname is the base outfilename, without its numeric add-on
  51. * 'jj' is the humeric extension which will be added to that root name.
  52. * 4) any INPUT file(s) to previous process MUST BE CLOSED before calling this function
  53. * 5) floats_out = number of float samples in analysis file
  54. * 6) samps_so_far is counter of TOTAL floats written out to any output files so far,
  55. * and is accumulated to the write-count sent to the timer-display bar by PVOC.
  56. * It does not affect counters in writing of file data.
  57. * Time-display for the process containing this function should be calculated as fraction of dz->tempsize,
  58. * which itself must hold the total of ALL the samps written out to ALL the files over the whole process.
  59. * 7) the original analysis file (input to this function) is closed AND DELETED by this process.
  60. * 8) mxfft() must be included in compilation, for this to work.
  61. */
  62. int pvoc_out
  63. (int floats_out,unsigned int *samps_so_far,char *orig_outfilename, char *root_outname, int jj, dataptr dz)
  64. {
  65. int exit_status;
  66. int orig_proctype, orig_chans, orig_stype;
  67. int orig_srate;
  68. int orig_infilecnt = dz->infilecnt;
  69. int len = strlen(orig_outfilename);
  70. char filename[256];
  71. int stype;
  72. /*RWD 2004 */
  73. char pfname[_MAX_PATH];
  74. //Create enough space to remember filename
  75. if(dz->wordstor == NULL) {
  76. if((dz->wordstor = (char **)malloc(sizeof(char *)))==NULL)
  77. return(MEMORY_ERROR);
  78. dz->wordstor[0] = NULL;
  79. if((dz->wordstor[0] = (char *)malloc((len + 1) * sizeof(char *)))==NULL)
  80. return(MEMORY_ERROR);
  81. } else {
  82. if(strlen(dz->wordstor[0]) < (unsigned int)len) {
  83. if((dz->wordstor[0] = (char *)realloc((char *)dz->wordstor[0],(len + 1) * sizeof(char *)))==NULL)
  84. return(MEMORY_ERROR);
  85. }
  86. }
  87. strcpy(dz->wordstor[0],orig_outfilename); /* save name of file in dz->wordstor[0]: in this case, no malloc reqd */
  88. strcpy(filename,root_outname); /* create new outfilename, for sound output */
  89. //TW REVISION new protocol : always pass outfile extension to cmdline
  90. insert_new_number_at_filename_end(filename,jj,0);
  91. dz->infilecnt = 2; /* tell system we have 1 inputfile */
  92. /*RWD Feb 2004 write full anal props so we can inspect etc */
  93. #ifdef _DEBUG
  94. if(sndputprop(dz->ofd,"original sampsize", (char *)&(dz->outfile->origstype), sizeof(int)) < 0){
  95. sprintf(errstr,"Failure to write original sample size. headwrite()\n");
  96. return(PROGRAM_ERROR);
  97. }
  98. if(sndputprop(dz->ofd,"original sample rate", (char *)&(dz->outfile->origrate), sizeof(int)) < 0){
  99. sprintf(errstr,"Failure to write original sample rate. headwrite()\n");
  100. return(PROGRAM_ERROR);
  101. }
  102. if(sndputprop(dz->ofd,"arate",(char *)&(dz->outfile->arate),sizeof(float)) < 0){
  103. sprintf(errstr,"Failed to write analysis sample rate. headwrite()\n");
  104. return(PROGRAM_ERROR);
  105. }
  106. if(sndputprop(dz->ofd,"analwinlen",(char *)&(dz->outfile->Mlen),sizeof(int)) < 0){
  107. sprintf(errstr,"Failure to write analysis window length. headwrite()\n");
  108. return(PROGRAM_ERROR);
  109. }
  110. if(sndputprop(dz->ofd,"decfactor",(char *)&(dz->outfile->Dfac),sizeof(int)) < 0){
  111. sprintf(errstr,"Failure to write decimation factor. headwrite()\n");
  112. return(PROGRAM_ERROR);
  113. }
  114. #endif
  115. /* set output file as input file */
  116. sndcloseEx(dz->ofd);
  117. dz->ofd = -1;
  118. if(dz->ifd == NULL)
  119. allocate_filespace(dz);
  120. if((dz->ifd[0] = sndopenEx(orig_outfilename,0,CDP_OPEN_RDONLY)) < 0) {
  121. sprintf(errstr,"Cannot reopen temporary analysis file '%s' to generate sound data:%s\n", orig_outfilename,sferrstr());
  122. return(SYSTEM_ERROR);
  123. }
  124. *samps_so_far += dz->total_samps_written;
  125. reset_file_params_for_sndout(&orig_proctype,&orig_srate,&orig_chans,&orig_stype,dz);
  126. if(dz->floatsam_output==1)
  127. stype = SAMP_FLOAT;
  128. else
  129. stype = SAMP_SHORT;
  130. dz->true_outfile_stype = stype;
  131. if((dz->ofd = sndcreat_formatted(filename,-1,stype,
  132. 1,(int)round(dz->param[SS_SRATE]),CDP_CREATE_NORMAL)) < 0) {
  133. sprintf(errstr,"Cannot open output intermediate soundfile %s\n", filename);
  134. return(DATA_ERROR);
  135. }
  136. dz->total_samps_written = 0L;
  137. dz->insams[0] = floats_out;
  138. /*RWD need retval - may run out of memory! */
  139. if((exit_status = pvoc_process_addon(*samps_so_far,dz)) < 0)
  140. //TW Bare messages break sound Loom messaging system
  141. return exit_status;
  142. samps_so_far += dz->total_samps_written;
  143. /*RWD Feb 2004 */
  144. if(dz->ifd[0] >= 0){
  145. strcpy(pfname,snd_getfilename(dz->ifd[0]));
  146. if(sndcloseEx(dz->ifd[0]) < 0) {
  147. sprintf(errstr,"Can't close intermediate analfile %s\n",orig_outfilename);
  148. return(SYSTEM_ERROR);
  149. }
  150. }
  151. dz->ifd[0] = -1;
  152. if(remove(/*orig_outfilename*/pfname)<0) {
  153. fprintf(stdout,"WARNING: Can't remove temporary analysis file %s\n",/*orig_outfilename*/pfname);
  154. fflush(stdout);
  155. }
  156. sndcloseEx(dz->ofd);
  157. reset_file_params_for_analout(orig_proctype,orig_srate,orig_chans,orig_stype,dz);
  158. dz->infilecnt = orig_infilecnt;
  159. return(FINISHED);
  160. }
  161. /****************************** HAMMING ******************************/
  162. #if 0
  163. void hamming(float *win,int winLen,int even)
  164. {
  165. float Pi,ftmp;
  166. int i;
  167. /***********************************************************
  168. Pi = (float)((double)4.*atan((double)1.));
  169. ***********************************************************/
  170. Pi = (float)PI;
  171. ftmp = Pi/winLen;
  172. if (even) {
  173. for (i=0; i<winLen; i++)
  174. *(win+i) = (float)((double).54 + (double).46*cos((double)(ftmp*((float)i+.5))));
  175. *(win+winLen) = 0.0f;}
  176. else{ *(win) = 1.0f;
  177. for (i=1; i<=winLen; i++)
  178. *(win+i) =(float)((double).54 + (double).46*cos((double)(ftmp*(float)i)));
  179. }
  180. return;
  181. }
  182. #endif
  183. /*RWD 22/03/18 maybe need to use this? */
  184. void vonhann(float *win,int winLen,int even)
  185. {
  186. float Pi,ftmp;
  187. int i;
  188. Pi = (float)PI;
  189. ftmp = Pi/winLen;
  190. if (even) {
  191. for (i=0; i<winLen; i++)
  192. *(win+i) = (float)(.5 + .5 *cos(ftmp*((double)i+.5)));
  193. *(win+winLen) = 0.0f;
  194. }
  195. else{ *(win) = 1.0f;
  196. for (i=1; i<=winLen; i++)
  197. *(win+i) =(float)(.5 + .5 *cos(ftmp*(double)i));
  198. }
  199. }
  200. /****************************** FLOAT_ARRAY ******************************/
  201. int pvoc_float_array(int nnn,float **ptr)
  202. { /* set up a floating point array length nnn. */
  203. *ptr = (float *) calloc(nnn,sizeof(float));
  204. if(*ptr==NULL){
  205. sprintf(errstr,"pvoc: insufficient memory\n");
  206. return(MEMORY_ERROR);
  207. }
  208. return(FINISHED);
  209. }
  210. /****************************** PVOC_PROCESS_ADDON ******************************/
  211. int pvoc_process_addon(unsigned int samps_so_far,dataptr dz)
  212. {
  213. int exit_status;
  214. int num_overflows = 0;
  215. int samptime = SAMP_TIME_STEP;
  216. float *input, /* pointer to start of input buffer */
  217. *output, /* pointer to start of output buffer */
  218. *anal, /* pointer to start of analysis buffer */
  219. *syn, /* pointer to start of synthesis buffer */
  220. // *banal, /* pointer to anal[1] (for FFT calls) */
  221. *bsyn, /* pointer to syn[1] (for FFT calls) */
  222. // *nextIn, /* pointer to next empty word in input */
  223. *nextOut, /* pointer to next empty word in output */
  224. *analWindow, /* pointer to center of analysis window */
  225. *synWindow, /* pointer to center of synthesis window */
  226. *maxAmp, /* pointer to start of max amp buffer */
  227. *avgAmp, /* pointer to start of avg amp buffer */
  228. *avgFrq, /* pointer to start of avg frq buffer */
  229. *env, /* pointer to start of spectral envelope */
  230. *i0, /* pointer to amplitude channels */
  231. *i1, /* pointer to frequency channels */
  232. *oldInPhase, /* pointer to start of input phase buffer */
  233. *oldOutPhase, /* pointer to start of output phase buffer */
  234. maxsample = 0.0, minsample = 0.0, biggest;
  235. int M = 0, /* length of analWindow impulse response */
  236. D = 0, /* decimation factor */
  237. I = 0, /* interpolation factor (default will be I=D)*/
  238. pvoc_chans = dz->infile->channels - 2,
  239. analWinLen, /* half-length of analysis window */
  240. synWinLen; /* half-length of synthesis window */
  241. int outCount, /* number of samples written to output */
  242. ibuflen, /* length of input buffer */
  243. obuflen, /* length of output buffer */
  244. nI = 0, /* current input (analysis) sample */
  245. nO, /* current output (synthesis) sample */
  246. nMaxOut; /* last output (synthesis) sample */
  247. int isr, /* sampling rate */
  248. endsamp = VERY_BIG_INT;
  249. float mag, /* magnitude of analysis data */
  250. phase, /* phase of analysis data */
  251. //RoverTwoPi, /* R/D divided by 2*Pi */
  252. TwoPioverR, /* 2*Pi divided by R/I */
  253. sum, /* scale factor for renormalizing windows */
  254. //rIn, /* decimated sampling rate */
  255. rOut, /* pre-interpolated sampling rate */
  256. R; /* input sampling rate */
  257. int i,j,k, /* index variables */
  258. Dd, /* number of new inputs to read (Dd <= D) */
  259. Ii, /* number of new outputs to write (Ii <= I) */
  260. N2, /* pvoc_chans/2 */
  261. NO, /* synthesis NO = pvoc_chans / P */
  262. NO2, /* NO/2 */
  263. IO, /* synthesis IO = I / P */
  264. IOi, /* synthesis IOi = Ii / P */
  265. Mf = 0, /* flag for even M */
  266. #ifdef SINGLE_SAMP
  267. rv, /* return value from fgetfloat */
  268. #endif
  269. flag = 0; /* end-of-input flag */
  270. float arate; /* sample rate for header on stdout if -A */
  271. /*RWD*/
  272. float F = 0.0f;
  273. #if defined(__SC__) && defined(SOFT_FP)
  274. extern int _8087;
  275. _8087 = 0;
  276. #endif
  277. {
  278. char *mem;
  279. if((mem = malloc(64*SECSIZE)) == 0
  280. //TW dz->snd_ifd no longer exists
  281. /* RWD Nov 2011 not allowed to call sndsetbuf these days! */
  282. /* ||sndsetbuf(dz->ifd[0], mem, 64) < 0 */ ) { /*RWD*/
  283. sprintf(errstr, "pvoc: Can't set big input buffer\n");
  284. return(MEMORY_ERROR);
  285. }
  286. }
  287. isr = dz->infile->origrate;
  288. arate = dz->infile->arate;
  289. M = dz->infile->Mlen;
  290. D = dz->infile->Dfac;
  291. R = ((float) D * arate);
  292. if(flteq(R,0.0)) {
  293. sprintf(errstr,"Problem: zero sampling rate\n");
  294. return(DATA_ERROR);
  295. }
  296. N2 = pvoc_chans / 2;
  297. F = /*(int)*/(R /(float)pvoc_chans);
  298. Mf = 1 - M%2;
  299. if (M < 7) {
  300. fprintf(stdout,"WARNING: analWindow impulse response is too small\n");
  301. fflush(stdout);
  302. }
  303. ibuflen = 4 * M;
  304. obuflen = 4 * M;
  305. I = D;
  306. NO = pvoc_chans; /* synthesis transform will be NO points */
  307. NO2 = NO/2;
  308. IO = I;
  309. if((exit_status = sndwrite_header(R,dz))<0)
  310. return(exit_status);
  311. /* set up analysis window: The window is assumed to be symmetric
  312. with M total points. After the initial memory allocation,
  313. analWindow always points to the midpoint of the window
  314. (or one half sample to the right, if M is even); analWinLen
  315. is half the true window length (rounded down). Any low pass
  316. window will work; a Hamming window is generally fine,
  317. but a Kaiser is also available. If the window duration is
  318. longer than the transform (M > N), then the window is
  319. multiplied by a sin(x)/x function to meet the condition:
  320. analWindow[Ni] = 0 for i != 0. In either case, the
  321. window is renormalized so that the phase vocoder amplitude
  322. estimates are properly scaled. The maximum allowable
  323. window duration is ibuflen/2. */
  324. if((exit_status = pvoc_float_array(M+Mf,&analWindow))<0)
  325. return(exit_status);
  326. analWindow += (analWinLen = M/2);
  327. //hamming(analWindow,analWinLen,Mf);
  328. vonhann(analWindow,analWinLen,Mf);
  329. for (i = 1; i <= analWinLen; i++)
  330. *(analWindow - i) = *(analWindow + i - Mf);
  331. if (M > pvoc_chans) {
  332. if (Mf)
  333. *analWindow *=(float)
  334. ((double)pvoc_chans*sin((double)PI*.5/pvoc_chans)/(double)(PI*.5));
  335. for (i = 1; i <= analWinLen; i++)
  336. *(analWindow + i) *=(float)
  337. ((double)pvoc_chans * sin((double) (PI*(i+.5*Mf)/pvoc_chans)) / (PI*(i+.5*Mf))); /*RWD*/
  338. for (i = 1; i <= analWinLen; i++)
  339. *(analWindow - i) = *(analWindow + i - Mf);
  340. }
  341. sum = 0.0f;
  342. for (i = -analWinLen; i <= analWinLen; i++)
  343. sum += *(analWindow + i);
  344. sum = (float)(2.0/sum); /*factor of 2 comes in later in trig identity*/
  345. for (i = -analWinLen; i <= analWinLen; i++)
  346. *(analWindow + i) *= sum;
  347. /* set up synthesis window: For the minimal mean-square-error
  348. formulation (valid for N >= M), the synthesis window
  349. is identical to the analysis window (except for a
  350. scale factor), and both are even in length. If N < M,
  351. then an interpolating synthesis window is used. */
  352. if((exit_status = pvoc_float_array(M+Mf,&synWindow))<0)
  353. return(exit_status);
  354. synWindow += (synWinLen = M/2);
  355. if (M <= pvoc_chans){
  356. //hamming(synWindow,synWinLen,Mf);
  357. vonhann(synWindow,synWinLen,Mf);
  358. for (i = 1; i <= synWinLen; i++)
  359. *(synWindow - i) = *(synWindow + i - Mf);
  360. for (i = -synWinLen; i <= synWinLen; i++)
  361. *(synWindow + i) *= sum;
  362. sum = 0.0f;
  363. for (i = -synWinLen; i <= synWinLen; i+=I)
  364. sum += *(synWindow + i) * *(synWindow + i);
  365. sum = (float)(1.0/ sum);
  366. for (i = -synWinLen; i <= synWinLen; i++)
  367. *(synWindow + i) *= sum;
  368. } else {
  369. //hamming(synWindow,synWinLen,Mf);
  370. vonhann(synWindow,synWinLen,Mf);
  371. for (i = 1; i <= synWinLen; i++)
  372. *(synWindow - i) = *(synWindow + i - Mf);
  373. if (Mf)
  374. *synWindow *= (float)((double)IO * sin((double) (PI*.5/IO)) / (double)(PI*.5));
  375. for (i = 1; i <= synWinLen; i++)
  376. *(synWindow + i) *=(float)
  377. ((double)IO * sin((double) (PI*(i+.5*Mf)/IO)) /(double) (PI*(i+.5*Mf)));
  378. for (i = 1; i <= synWinLen; i++)
  379. *(synWindow - i) = *(synWindow + i - Mf);
  380. sum = (float)(1.0/sum);
  381. for (i = -synWinLen; i <= synWinLen; i++)
  382. *(synWindow + i) *= sum;
  383. }
  384. /* set up input buffer: nextIn always points to the next empty
  385. word in the input buffer (i.e., the sample following
  386. sample number (n + analWinLen)). If the buffer is full,
  387. then nextIn jumps back to the beginning, and the old
  388. values are written over. */
  389. if((exit_status = pvoc_float_array(ibuflen,&input))<0)
  390. return(exit_status);
  391. // nextIn = input;
  392. /* set up output buffer: nextOut always points to the next word
  393. to be shifted out. The shift is simulated by writing the
  394. value to the standard output and then setting that word
  395. of the buffer to zero. When nextOut reaches the end of
  396. the buffer, it jumps back to the beginning. */
  397. if((exit_status = pvoc_float_array(obuflen,&output))<0)
  398. return(exit_status);
  399. nextOut = output;
  400. /* set up analysis buffer for (N/2 + 1) channels: The input is real,
  401. so the other channels are redundant. oldInPhase is used
  402. in the conversion to remember the previous phase when
  403. calculating phase difference between successive samples. */
  404. if((exit_status = pvoc_float_array(pvoc_chans+2,&anal))<0)
  405. return(exit_status);
  406. if((exit_status = pvoc_float_array(N2+1,&oldInPhase))<0)
  407. return(exit_status);
  408. if((exit_status = pvoc_float_array(N2+1,&maxAmp))<0)
  409. return(exit_status);
  410. if((exit_status = pvoc_float_array(N2+1,&avgAmp))<0)
  411. return(exit_status);
  412. if((exit_status = pvoc_float_array(N2+1,&avgFrq))<0)
  413. return(exit_status);
  414. if((exit_status = pvoc_float_array(N2+1,&env))<0)
  415. return(exit_status);
  416. /* set up synthesis buffer for (pvoc_chans/2 + 1) channels: (This is included
  417. only for clarity.) oldOutPhase is used in the re-
  418. conversion to accumulate angle differences (actually angle
  419. difference per second). */
  420. if((exit_status = pvoc_float_array(NO+2,&syn))<0)
  421. return(exit_status);
  422. bsyn = syn + 1;
  423. if((exit_status = pvoc_float_array(NO2+1,&oldOutPhase))<0)
  424. return(exit_status);
  425. /* initialization: input time starts negative so that the rightmost
  426. edge of the analysis filter just catches the first non-zero
  427. input samples; output time is always T times input time. */
  428. outCount = 0;
  429. //rIn = (float)(R/(float)D);
  430. rOut = (float)(R/(float)I);
  431. //RoverTwoPi = (float)(rIn/TWOPI);
  432. TwoPioverR = (float)(TWOPI/rOut);
  433. nI = -(analWinLen / D) * D; /* input time (in samples) */
  434. nO = nI; /* output time (in samples) */
  435. Dd = analWinLen + nI + 1; /* number of new inputs to read */
  436. Ii = 0; /* number of new outputs to write */
  437. IOi = 0;
  438. flag = 1;
  439. /* main loop: If endsamp is not specified it is assumed to be very large
  440. and then readjusted when fgetfloat detects the end of input. */
  441. while(nI < (endsamp + analWinLen)){
  442. #ifdef SINGLE_SAMP
  443. for (i = 0; i < pvoc_chans+2; i++){ /* synthesis only */
  444. if ((rv = fgetfloat((anal+i),dz->ifd[0])) <= 0){
  445. goto epilog;
  446. }
  447. }
  448. #else
  449. //TW snd_ibuf no longer exists
  450. if((i = fgetfbufEx(anal, pvoc_chans+2, dz->ifd[0],0)) < 0) { /*RWD*/
  451. sfperror("pvoc: read error: ");
  452. return(PROGRAM_ERROR);
  453. }
  454. if(i < pvoc_chans+2)
  455. goto epilog;
  456. #endif
  457. /* reconversion: The magnitude and angle-difference-per-second in syn
  458. (assuming an intermediate sampling rate of rOut) are
  459. converted to real and imaginary values and are returned in syn.
  460. This automatically incorporates the proper phase scaling for
  461. time modifications. */
  462. if (NO <= pvoc_chans){
  463. for (i = 0; i < NO+2; i++)
  464. *(syn+i) = *(anal+i);
  465. } else {
  466. for (i = 0; i <= pvoc_chans+1; i++)
  467. *(syn+i) = *(anal+i);
  468. for (i = pvoc_chans+2; i < NO+2; i++)
  469. *(syn+i) = 0.0f;
  470. }
  471. for(i=0, i0=syn, i1=syn+1; i<= NO2; i++,i0+=2,i1+=2) {
  472. mag = *i0;
  473. *(oldOutPhase + i) += *i1 - ((float) i * F);
  474. phase = *(oldOutPhase + i) * TwoPioverR;
  475. *i0 = (float)((double)mag * cos((double)phase));
  476. *i1 = (float)((double)mag * sin((double)phase));
  477. }
  478. /* synthesis: The synthesis subroutine uses the Weighted Overlap-Add
  479. technique to reconstruct the time-domain signal. The (pvoc_chans/2 + 1)
  480. phase vocoder channel outputs at time n are inverse Fourier
  481. transformed, windowed, and added into the output array. The
  482. subroutine thinks of output as a shift register in which
  483. locations are referenced modulo obuflen. Therefore, the main
  484. program must take care to zero each location which it "shifts"
  485. out (to standard output). The subroutines reals and fft
  486. together perform an efficient inverse FFT. */
  487. if((exit_status = reals_(syn,bsyn,NO2,2))<0)
  488. return(exit_status);
  489. if((exit_status = fft_(syn,bsyn,1,NO2,1,2))<0)
  490. return(exit_status);
  491. j = nO - synWinLen - 1;
  492. while (j < 0)
  493. j += obuflen;
  494. j = j % obuflen;
  495. k = nO - synWinLen - 1;
  496. while (k < 0)
  497. k += NO;
  498. k = k % NO;
  499. for (i = -synWinLen; i <= synWinLen; i++) { /*overlap-add*/
  500. if (++j >= obuflen)
  501. j -= obuflen;
  502. if (++k >= NO)
  503. k -= NO;
  504. *(output + j) += *(syn + k) * *(synWindow + i);
  505. }
  506. #ifdef SINGLE_SAMP
  507. for (i = 0; i < IOi; i++) { /* shift out next IOi values */
  508. fputfloat(nextOut,dz->ofd);
  509. *(nextOut++) = 0.;
  510. if (nextOut >= (output + obuflen))
  511. nextOut -= obuflen;
  512. outCount++;
  513. }
  514. #else
  515. for (i = 0; i < IOi;) { /* shift out next IOi values */
  516. int j;
  517. int todo = min(IOi-i, output+obuflen-nextOut);
  518. if((exit_status = outfloats(nextOut,&maxsample,&minsample,&num_overflows,todo, dz))<0)
  519. return(exit_status);
  520. i += todo;
  521. outCount += todo;
  522. for(j = 0; j < todo; j++)
  523. *nextOut++ = 0.0f;
  524. if (nextOut >= (output + obuflen))
  525. nextOut -= obuflen;
  526. }
  527. #endif
  528. if(flag /* flag means do this operation only once */
  529. && (nI > 0) && (Dd < D)) { /* EOF detected */
  530. flag = 0;
  531. endsamp = nI + analWinLen - (D - Dd);
  532. }
  533. nI += D; /* increment time */
  534. nO += IO;
  535. /* Dd = D except when the end of the sample stream intervenes */
  536. Dd = min(D, max(0, D+endsamp-nI-analWinLen));
  537. if (nO > (synWinLen + I))
  538. Ii = I;
  539. else if (nO > synWinLen)
  540. Ii = nO - synWinLen;
  541. else {
  542. Ii = 0;
  543. for (i=nO+synWinLen; i<obuflen; i++) {
  544. if (i > 0)
  545. *(output+i) = 0.0f;
  546. }
  547. }
  548. IOi = Ii;
  549. if(nI > samptime && (exit_status = pvoc_time_display(nI,samps_so_far,isr,&samptime,dz))<0)
  550. return(exit_status);
  551. } /* End of main while loop */
  552. nMaxOut = endsamp;
  553. while (outCount <= nMaxOut){
  554. #ifdef SINGLE_SAMP
  555. outCount++;
  556. fputfloat(nextOut++,dz->ofd);
  557. if (nextOut >= (output + obuflen))
  558. nextOut -= obuflen;
  559. #else
  560. int todo = min(nMaxOut-outCount, output+obuflen-nextOut);
  561. if(todo == 0)
  562. break;
  563. if((exit_status = outfloats(nextOut,&maxsample,&minsample,&num_overflows,todo, dz))<0)
  564. return(exit_status);
  565. outCount += todo;
  566. nextOut += todo;
  567. if (nextOut >= (output + obuflen))
  568. nextOut -= obuflen;
  569. #endif
  570. }
  571. if((exit_status = pvoc_time_display((int)endsamp,samps_so_far,isr,&samptime,dz))<0)
  572. return(exit_status);
  573. epilog:
  574. #ifndef NOOVERCHK
  575. if(num_overflows > 0) {
  576. biggest = maxsample;
  577. if(-minsample > maxsample)
  578. biggest = -minsample;
  579. fprintf(stdout, "WARNING: %d samples overflowed, and were clipped\n",num_overflows);
  580. fprintf(stdout, "WARNING: maximum sample was %f : minimum sample was %f\n",maxsample,minsample);
  581. fprintf(stdout, "WARNING: You should reduce source level to avoid clipping: use gain of <= %lf\n",1.0/biggest);
  582. fflush(stdout);
  583. }
  584. #endif
  585. return(FINISHED);
  586. }
  587. /*MCA
  588. * Convert floats -> shorts explicitly, since we are compiled with
  589. * hardware FP(probably), and the sound filing system is not!
  590. * (even without this, it should be more efficient!)
  591. */
  592. //TW NO CONVERSION TO FLOATS NEEDED 2002
  593. int outfloats(float *nextOut,float *maxsample,float *minsample,int *num_overflows,int todo, dataptr dz)
  594. {
  595. static float *sbuf = 0;
  596. static int sblen = 0;
  597. float *sp;
  598. int cnt;
  599. float val;
  600. if(sblen < todo) {
  601. if(sbuf != 0)
  602. free(sbuf);
  603. if((sbuf = (float *)malloc(todo*sizeof(float))) == 0) {
  604. sprintf(errstr, "pvoc: can't allocate output buffer\n");
  605. return(MEMORY_ERROR);
  606. }
  607. sblen = todo;
  608. }
  609. sp = sbuf;
  610. #ifdef NOOVERCHK
  611. for(cnt = 0; cnt < todo; cnt++)
  612. *sp++ = *nextOut++;
  613. #else
  614. for(cnt = 0; cnt < todo; cnt++) {
  615. val = *nextOut++;
  616. if(val >= 1.0 || val <= -1.0) {
  617. (*num_overflows)++;
  618. if(val > 0.0f) {
  619. if(val > *maxsample)
  620. *maxsample = val;
  621. val = 1.0f;
  622. }
  623. if(val < 0.0f) {
  624. if(val < *minsample)
  625. *minsample = val;
  626. val = -1.0f;
  627. }
  628. }
  629. *sp++ = val;
  630. }
  631. #endif
  632. // if(fputfbufEx(sbuf, todo, ofd) < todo) {
  633. if(todo > 0) {
  634. if(write_samps(sbuf, todo, dz) < 0) {
  635. sfperror("pvoc: write error");
  636. return(SYSTEM_ERROR);;
  637. }
  638. }
  639. //TW UPDATE
  640. return FINISHED;
  641. }
  642. /************************************ SNDWRITE_HEADER ************************************/
  643. /*RWD changed dz->ofd to to dz->ofd */
  644. int sndwrite_header(float R,dataptr dz)
  645. {
  646. int Nchans = 1;
  647. int isr = (int)R;
  648. if(sndputprop(dz->ofd,"sample rate",(char *)&isr,sizeof(int)) < 0 )
  649. fprintf(stdout,"WARNING: failed to write sample rate\n");
  650. if(sndputprop(dz->ofd,"channels",(char *)&Nchans,sizeof(int)) < 0 )
  651. fprintf(stdout,"WARNING: failed to write channel data\n");
  652. fflush(stdout);
  653. return(FINISHED);
  654. }
  655. /*********************************** PVOC_TIME_DISPLAY ***********************************/
  656. int pvoc_time_display(int nI,unsigned int samps_so_far,int srate,int *samptime,dataptr dz)
  657. {
  658. int true_chans, true_srate;
  659. true_chans = dz->infile->channels;
  660. true_srate = dz->infile->srate;
  661. dz->infile->channels = 1;
  662. dz->infile->srate = srate;
  663. display_virtual_time(nI + samps_so_far,dz);
  664. dz->infile->channels = true_chans;
  665. dz->infile->srate = true_srate;
  666. *samptime += SAMP_TIME_STEP;
  667. return(FINISHED);
  668. }
  669. /*void get_name_of_intermediate_file(char *filename,char *nufilename)
  670. {
  671. char temp[256];
  672. char *p;
  673. strcpy(nufilename,filename);
  674. p = nufilename + strlen(nufilename) - 1;
  675. while(p > nufilename) {
  676. if(*p == '/' || *p == '\\' || *p == ':') {
  677. p = nufilename;
  678. break;
  679. }
  680. if(*p == '.') {
  681. p--;
  682. c = *p;
  683. c += 2;
  684. *p = c;
  685. return;
  686. }
  687. p--;
  688. }
  689. if(p == nufilename) {
  690. p = nufilename + strlen(nufilename) - 1;
  691. c = *p;
  692. c += 2;
  693. *p = c;
  694. }
  695. }
  696. */
  697. void reset_file_params_for_sndout
  698. (int *orig_proctype,int *orig_srate,int *orig_chans,int *orig_stype,dataptr dz) {
  699. int stype;
  700. if(dz->floatsam_output==1 )
  701. stype= SAMP_FLOAT;
  702. else
  703. stype = SAMP_SHORT;
  704. dz->true_outfile_stype = stype;
  705. *orig_proctype = dz->process_type;
  706. *orig_srate = dz->outfile->srate;
  707. *orig_chans = dz->outfile->channels;
  708. *orig_stype = dz->outfile->stype;
  709. dz->process_type = UNEQUAL_SNDFILE;
  710. dz->outfile->srate = dz->infile->srate = dz->iparam[SS_SRATE];
  711. dz->outfile->channels = MONO;
  712. dz->outfile->stype = /* dz->outfile->stype = */ stype; /* RWD: should that be infile->stype? */
  713. }
  714. void reset_file_params_for_analout
  715. (int orig_proctype,int orig_srate,int orig_chans,int orig_stype,dataptr dz) {
  716. dz->process_type = orig_proctype;
  717. dz->outfile->srate = dz->infile->srate = orig_srate;
  718. dz->outfile->channels = orig_chans;
  719. dz->outfile->stype = /* dz->outfile->stype = */ orig_stype;
  720. }