pvoc_addon.c 30 KB

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