paudition.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  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. /* PEDITAUD
  22. *
  23. * Hear a pitchfile being edited in the PDISPLAY routine in SoundLoom.
  24. */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <osbind.h>
  29. #include <math.h>
  30. #include <float.h>
  31. #include <float.h>
  32. #include <sfsys.h>
  33. #include <cdplib.h>
  34. #include <pvoc.h>
  35. #include <paudition.h>
  36. char errstr[2400];
  37. #define NOT_PITCH (-1.0)
  38. #define ENDOFSTR ('\0')
  39. #define ANALFILE_OUT (1)
  40. #define SNDFILE_OUT (0)
  41. #define WINDOW_AMP (0.5)
  42. #define PARTIALS_IN_TEST_TONE (6)
  43. #define PARTIAL_DECIMATION (.25)
  44. #define VERY_TINY_AMP (0.00000000000000000001) /* 10^-20 */
  45. #define FLTERR (0.000002)
  46. static int headwrite(int ofd,int origstype,int origrate,float arate,int Mlen,int Dfac);
  47. static int get_data_from_pitchfile(float **pitches,int infilesize,int ifd);
  48. static int setup_amplitudes(int clength,double halfchwidth,double chwidth,float **testpamp,float **totpamp,float **chbot);
  49. static void do_finish(int n,int ifd,int ofd,float *bigbuf) ;
  50. static int make_buffer(float **bigbuf,int *big_fsize, int wanted);
  51. static int gen_testdata(int ofd,float *bigbuf,float *bigbufend,int big_fsize,
  52. int wlength,int clength,int wanted,int *total_samps_written,float *pitches,
  53. double chwidth,double halfchwidth,float *chbot,double nois_chanamp,float *testpamp,float *totpamp,
  54. double nyquist,double pre_totalamp);
  55. static void gen_silence_in_sampbuf(float *sampbuf,double chwidth,double halfchwidth,int clength,
  56. float *chbot,double nois_chanamp);
  57. static void gen_nois_in_sampbuf(float *sampbuf,double chwidth,double halfchwidth,int clength,
  58. float *chbot,double nois_chanamp);
  59. static void gen_tone_in_sampbuf(double thisfrq,float *sampbuf,float *testpamp,float *totpamp,
  60. double nyquist,double pre_totalamp,double chwidth,double halfchwidth,int wanted);
  61. static int pvoc_process_addon(int ifd,int ofd,int chans,int origrate,float arate,int Mlen,int Dfac);
  62. static void hamming(float *win,int winLen,int even);
  63. static int pvoc_float_array(int nnn,float **ptr);
  64. /*static int lcm(int a, int b);*/
  65. static void preset_sampbuf(float *sampbuf,double halfchwidth, int clength, float *chbot);
  66. static void normalise(double post_totalamp,double pre_totalamp,int wanted,float *sampbuf);
  67. static int flteq(double f1,double f2);
  68. static int outfloats(float *nextOut,float *maxsample,float *minsample,int *num_overflows,int todo, int ofd);
  69. #define MONO (1)
  70. const char* cdp_version = "7.1.0";
  71. int main(int argc,char *argv[])
  72. {
  73. float *pitches, *testpamp, *totpamp, *chbot;
  74. float *bigbuf = NULL, *bigbufend;
  75. int big_fsize, total_samps_written = 0;
  76. int ofd = -1, ifd;
  77. int wlength;
  78. int origchans, origstype, origrate;
  79. float arate;
  80. int Mlen, Dfac;
  81. int srate, chans;
  82. double chwidth, halfchwidth, nyquist, nois_chanamp, gain = 1.0, pre_totalamp;
  83. int wanted, clength;
  84. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  85. fprintf(stdout,"%s\n",cdp_version);
  86. fflush(stdout);
  87. return 0;
  88. }
  89. if(argc != 12) {
  90. fprintf(stdout,"ERROR: Incorrect call to program which writes the sound.\n");
  91. fflush(stdout);
  92. return 1;
  93. }
  94. /* initialise SFSYS */
  95. if( sflinit("paudition") < 0 ) {
  96. fprintf(stdout,"ERROR: Cannot initialise soundfile system.\n");
  97. fflush(stdout);
  98. return 1;
  99. }
  100. /* open input file */
  101. if((ifd = sndopenEx(argv[1],0,CDP_OPEN_RDONLY))<0) {
  102. fprintf(stdout,"INFO: Cannot open intermediate pitch data file: %s\n",argv[1]);
  103. fflush(stdout);
  104. do_finish(0,ifd,ofd,bigbuf);
  105. }
  106. wlength = sndsizeEx(ifd);
  107. if(sscanf(argv[4],"%d",&origchans)!=1) {
  108. fprintf(stdout,"ERROR: Cannot read original-channels data,\n");
  109. fflush(stdout);
  110. do_finish(1,ifd,ofd,bigbuf);
  111. return 1;
  112. }
  113. if(sscanf(argv[5],"%d",&origstype)!=1) {
  114. fprintf(stdout,"ERROR: Cannot read original-sample-type data,\n");
  115. fflush(stdout);
  116. do_finish(1,ifd,ofd,bigbuf);
  117. return 1;
  118. }
  119. if(sscanf(argv[6],"%d",&origrate)!=1) {
  120. fprintf(stdout,"ERROR: Cannot read original-sample-rate data,\n");
  121. fflush(stdout);
  122. do_finish(1,ifd,ofd,bigbuf);
  123. return 1;
  124. }
  125. if(sscanf(argv[7],"%f",&arate)!=1) {
  126. fprintf(stdout,"ERROR: Cannot read analysis-rate data,\n");
  127. fflush(stdout);
  128. do_finish(1,ifd,ofd,bigbuf);
  129. return 1;
  130. }
  131. if(sscanf(argv[8],"%d",&Mlen)!=1) {
  132. fprintf(stdout,"ERROR: Cannot read Mlen data,\n");
  133. fflush(stdout);
  134. do_finish(1,ifd,ofd,bigbuf);
  135. return 1;
  136. }
  137. if(sscanf(argv[9],"%d",&Dfac)!=1) {
  138. fprintf(stdout,"ERROR: Cannot read Decimation Factor data,\n");
  139. fflush(stdout);
  140. do_finish(1,ifd,ofd,bigbuf);
  141. return 1;
  142. }
  143. if(sscanf(argv[10],"%d",&srate)!=1) {
  144. fprintf(stdout,"ERROR: Cannot read sample-rate data,\n");
  145. fflush(stdout);
  146. do_finish(1,ifd,ofd,bigbuf);
  147. return 1;
  148. }
  149. if(sscanf(argv[11],"%d",&chans)!=1) {
  150. fprintf(stdout,"ERROR: Cannot read channel data,\n");
  151. fflush(stdout);
  152. do_finish(1,ifd,ofd,bigbuf);
  153. return 1;
  154. }
  155. //TW COMMENT: this is temporary analysis file
  156. if((ofd = sndcreat_formatted(argv[2],-1,SAMP_FLOAT,
  157. chans,srate,CDP_CREATE_NORMAL)) < 0) {
  158. fprintf(stdout,"ERROR: Can't create file %s (It may already exist)\n", argv[2]);
  159. fflush(stdout);
  160. do_finish(1,ifd,ofd,bigbuf);
  161. return 1;
  162. }
  163. wanted = origchans ; /* floatsams to read */
  164. clength = wanted / 2; /* channels to process */
  165. nyquist = (double)origrate/2.0;
  166. chwidth = nyquist/(double)(clength - 1);
  167. halfchwidth = chwidth/2.0;
  168. if(!get_data_from_pitchfile(&pitches,wlength,ifd)) {
  169. do_finish(2,ifd,ofd,bigbuf);
  170. return 1;
  171. }
  172. sndcloseEx(ifd);
  173. pre_totalamp = WINDOW_AMP * gain;
  174. nois_chanamp = pre_totalamp/(double)clength;
  175. if(!setup_amplitudes(clength,halfchwidth,chwidth,&testpamp,&totpamp,&chbot)) {
  176. do_finish(3,ifd,ofd,bigbuf);
  177. return 1;
  178. }
  179. if(!make_buffer(&bigbuf,&big_fsize,wanted)) {
  180. do_finish(3,ifd,ofd,bigbuf);
  181. return 1;
  182. }
  183. bigbufend = bigbuf + big_fsize;
  184. if(!gen_testdata(ofd,bigbuf,bigbufend,big_fsize,wlength,clength,wanted,&total_samps_written,
  185. pitches,chwidth,halfchwidth,chbot,nois_chanamp,testpamp,totpamp,nyquist,pre_totalamp)) {
  186. do_finish(4,ifd,ofd,bigbuf);
  187. return 1;
  188. }
  189. chans = origchans;
  190. if (!headwrite(ofd,origstype,origrate,arate,Mlen,Dfac)) {
  191. fprintf(stdout,"ERROR: Failed to write valid header to output file.\n");
  192. fflush(stdout);
  193. do_finish(4,ifd,ofd,bigbuf);
  194. return 1;
  195. }
  196. Mfree(bigbuf);
  197. sndcloseEx(ofd);
  198. if((ifd = sndopenEx(argv[2],0,CDP_OPEN_RDONLY))<0) {
  199. fprintf(stdout,"INFO: Cannot open intermediate analysis data file: %s\n",argv[2]);
  200. fflush(stdout);
  201. do_finish(0,ifd,ofd,bigbuf);
  202. return 1;
  203. }
  204. //TW COMMENT as this is a temporary sndfile: may as well leave it as SAMP_SHORT
  205. if((ofd = sndcreat_formatted(argv[3],-1,SAMP_SHORT,
  206. MONO,origrate,CDP_CREATE_NORMAL)) < 0) {
  207. fprintf(stdout,"ERROR: Can't create output soundfile %s\n", argv[3]);
  208. fflush(stdout);
  209. do_finish(5,ifd,ofd,bigbuf);
  210. return 1;
  211. }
  212. if(!pvoc_process_addon(ifd,ofd,chans,origrate,arate,Mlen,Dfac)) {
  213. do_finish(6,ifd,ofd,bigbuf);
  214. return 1;
  215. }
  216. do_finish(6,ifd,ofd,bigbuf);
  217. return 1;
  218. }
  219. /***************************** HEADWRITE *******************************/
  220. int headwrite(int ofd,int origstype,int origrate,float arate,int Mlen,int Dfac)
  221. {
  222. if(sndputprop(ofd,"original sampsize", (char *)&origstype, sizeof(int)) < 0){
  223. fprintf(stdout,"ERROR: Failure to write original sample size. headwrite()\n");
  224. fflush(stdout);
  225. return(0);
  226. }
  227. if(sndputprop(ofd,"original sample rate", (char *)&origrate, sizeof(int)) < 0){
  228. fprintf(stdout,"ERROR: Failure to write original sample rate. headwrite()\n");
  229. fflush(stdout);
  230. return(0);
  231. }
  232. if(sndputprop(ofd,"arate",(char *)&arate,sizeof(float)) < 0){
  233. fprintf(stdout,"ERROR: Failed to write analysis sample rate. headwrite()\n");
  234. fflush(stdout);
  235. return(0);
  236. }
  237. if(sndputprop(ofd,"analwinlen",(char *)&Mlen,sizeof(int)) < 0){
  238. fprintf(stdout,"ERROR: Failure to write analysis window length. headwrite()\n");
  239. fflush(stdout);
  240. return(0);
  241. }
  242. if(sndputprop(ofd,"decfactor",(char *)&Dfac,sizeof(int)) < 0){
  243. fprintf(stdout,"ERROR: Failure to write decimation factor. headwrite()\n");
  244. fflush(stdout);
  245. return(0);
  246. }
  247. return(1);
  248. }
  249. /********************* GET_DATA_FROM_PITCHFILE *************************/
  250. int get_data_from_pitchfile(float **pitches,int wanted,int ifd)
  251. {
  252. int samps_read;
  253. if((*pitches = (float *)malloc(wanted * sizeof(float)))==NULL) {
  254. fprintf(stdout,"ERROR: Insufficient memory to reread pitchdata.\n");
  255. fflush(stdout);
  256. return 0;
  257. }
  258. if((samps_read = fgetfbufEx(*pitches, wanted,ifd,0))<0) {
  259. fprintf(stdout,"ERROR: Cannot reread pitchdata.\n");
  260. fflush(stdout);
  261. return 0;
  262. }
  263. if(samps_read!=wanted) {
  264. fprintf(stdout,"ERROR: Problem rereading pitch data.\n");
  265. fflush(stdout);
  266. return 0;
  267. }
  268. return(1);
  269. }
  270. /****************************** SETUP_AMPLITUDES ***************/
  271. int setup_amplitudes(int clength,double halfchwidth,double chwidth,float **testpamp,float **totpamp,float **chbot)
  272. {
  273. int n, cc;
  274. if((*testpamp = (float *)malloc(PARTIALS_IN_TEST_TONE * sizeof(float)))==NULL) {
  275. fprintf(stdout,"ERROR: Insufficient memory A.\n");
  276. fflush(stdout);
  277. return 0;
  278. }
  279. if((*totpamp = (float *)malloc(PARTIALS_IN_TEST_TONE * sizeof(float)))==NULL) {
  280. fprintf(stdout,"ERROR: Insufficient memory B.\n");
  281. fflush(stdout);
  282. return 0;
  283. }
  284. (*totpamp)[0] = (*testpamp)[0] = 0.5f;
  285. for(n = 1; n < PARTIALS_IN_TEST_TONE; n++) /* ACTUAL PARTIAL AMPS */
  286. (*testpamp)[n] = (float)((*testpamp)[n-1] * PARTIAL_DECIMATION);
  287. for(n = 1; n < PARTIALS_IN_TEST_TONE; n++) /* SUM OF PARTIAL AMPS */
  288. (*totpamp)[n] = (float)((*totpamp)[n-1] + (*testpamp)[n]);
  289. if((*chbot = (float *)malloc(clength * sizeof(float)))==NULL) {
  290. fprintf(stdout,"ERROR: Insufficient memory C.\n");
  291. fflush(stdout);
  292. return 0;
  293. }
  294. (*chbot)[0] = 0.0f;
  295. (*chbot)[1] = (float)halfchwidth;
  296. for(cc = 2 ;cc < clength; cc++)
  297. (*chbot)[cc] = (float)((*chbot)[cc-1] + chwidth);
  298. return 1;
  299. }
  300. /****************************** DO_FINISH *********************************/
  301. void do_finish(int n,int ifd,int ofd,float *bigbuf)
  302. {
  303. switch(n) {
  304. case(2):
  305. sndcloseEx(ofd);
  306. case(1):
  307. sndcloseEx(ifd);
  308. case(0):
  309. // sffinish();
  310. break;
  311. case(4):
  312. Mfree(bigbuf);
  313. case(3):
  314. sndcloseEx(ofd);
  315. // sffinish();
  316. break;
  317. case(6):
  318. sndcloseEx(ofd);
  319. case(5):
  320. sndcloseEx(ifd);
  321. // sffinish();
  322. break;
  323. }
  324. }
  325. /****************************** MAKE_BUFFER *********************************/
  326. int make_buffer(float **bigbuf,int *big_fsize, int wanted)
  327. {
  328. size_t bigbufsize = (size_t) Malloc(-1);
  329. *big_fsize = bigbufsize/sizeof(float);
  330. if((*big_fsize = ((*big_fsize)/wanted) * wanted)<=0) {
  331. fprintf(stdout,"ERROR: Insufficient memory E.\n");
  332. fflush(stdout);
  333. return 0;
  334. }
  335. if((*bigbuf = (float*)Malloc(*big_fsize * sizeof(float)))==NULL) {
  336. fprintf(stdout,"ERROR: Insufficient memory F.\n");
  337. fflush(stdout);
  338. return 0;
  339. }
  340. memset((char *)(*bigbuf),0,(*big_fsize * sizeof(float)));
  341. return 1;
  342. }
  343. /************************* GEN_TESTDATA *************************/
  344. int gen_testdata(int ofd,float *bigbuf,float *bigbufend,int big_fsize,
  345. int wlength,int clength,int wanted,int *total_samps_written,float *pitches,
  346. double chwidth,double halfchwidth,float *chbot,double nois_chanamp,float *testpamp,float *totpamp,
  347. double nyquist,double pre_totalamp)
  348. {
  349. double thisfrq;
  350. int n = 0, samps_to_write, samps_written;
  351. float *sampbuf = bigbuf;
  352. int cc, vc;
  353. while(n < wlength) {
  354. thisfrq = (double)pitches[n];
  355. if(thisfrq < NOT_PITCH) /* NO SOUND FOUND : GENERATE SILENCE */
  356. gen_silence_in_sampbuf(sampbuf,chwidth,halfchwidth,clength,chbot,nois_chanamp);
  357. else if(thisfrq < 0.0) /* NO PITCH FOUND : GENERATE NOISE */
  358. gen_nois_in_sampbuf(sampbuf,chwidth,halfchwidth,clength,chbot,nois_chanamp);
  359. else { /* GENERATE TESTTONE AT FOUND PITCH */
  360. preset_sampbuf(sampbuf,halfchwidth,clength,chbot);
  361. gen_tone_in_sampbuf(thisfrq,sampbuf,testpamp,totpamp,nyquist,pre_totalamp,chwidth,halfchwidth,wanted);
  362. }
  363. if(n==0) {
  364. for(cc = 0, vc = 0; cc < clength; cc++, vc += 2)
  365. sampbuf[vc] = 0.0f;
  366. }
  367. if((sampbuf += wanted) >= bigbufend) {
  368. if((samps_written = fputfbufEx(bigbuf,big_fsize,ofd))<0) {
  369. fprintf(stdout,"ERROR: Can't write to analysis file.\n");
  370. fflush(stdout);
  371. return 0;
  372. }
  373. *total_samps_written += big_fsize;
  374. memset((char *)bigbuf,0,big_fsize * sizeof(float));
  375. sampbuf = bigbuf;
  376. }
  377. n++;
  378. }
  379. if(sampbuf != bigbuf) {
  380. samps_to_write = (sampbuf - bigbuf);
  381. *total_samps_written += samps_to_write;
  382. if((samps_written = fputfbufEx(bigbuf,samps_to_write,ofd))<0) {
  383. fprintf(stdout,"ERROR: Can't write to analysis file.\n");
  384. fflush(stdout);
  385. return 0;
  386. }
  387. }
  388. return 1;
  389. }
  390. /*************************** GEN_SILENCE_IN_SAMPBUF *********************/
  391. void gen_silence_in_sampbuf(float *sampbuf,double chwidth,double halfchwidth,int clength,
  392. float *chbot,double nois_chanamp)
  393. {
  394. int cc, vc, clength_less_1 = clength - 1;
  395. sampbuf[0] = (float)nois_chanamp;
  396. sampbuf[1] = (float)(drand48() * halfchwidth);
  397. for(cc = 1, vc = 2; cc < clength_less_1; cc++, vc += 2) {
  398. sampbuf[vc+1] = (float)((drand48() * chwidth) + chbot[cc]);
  399. sampbuf[vc] = 0.0f;
  400. }
  401. sampbuf[vc+1] = (float)((drand48() * halfchwidth) + chbot[cc]);
  402. sampbuf[vc] = 0.0f;
  403. }
  404. /*************************** GEN_NOIS_IN_SAMPBUF *********************/
  405. void gen_nois_in_sampbuf(float *sampbuf,double chwidth,double halfchwidth,int clength,
  406. float *chbot,double nois_chanamp)
  407. {
  408. int cc, vc, clength_less_1 = clength - 1;
  409. sampbuf[0] = (float)nois_chanamp;
  410. sampbuf[1] = (float)(drand48() * halfchwidth);
  411. for(cc = 1, vc = 2; cc < clength_less_1; cc++, vc += 2) {
  412. sampbuf[vc+1] = (float)((drand48() * chwidth) + chbot[cc]);
  413. sampbuf[vc] = (float)nois_chanamp;
  414. }
  415. sampbuf[vc+1] = (float)((drand48() * halfchwidth) + chbot[cc]);
  416. sampbuf[vc] = (float)nois_chanamp;
  417. }
  418. /********************** GEN_TONE_IN_SAMPBUF ***************************/
  419. void gen_tone_in_sampbuf(double thisfrq,float *sampbuf,float *testpamp,float *totpamp,
  420. double nyquist,double pre_totalamp,double chwidth,double halfchwidth,int wanted)
  421. {
  422. int cc, vc, m, ampadjusted = 0;
  423. int lastvc = -1;
  424. double post_totalamp;
  425. for(m=0;m<PARTIALS_IN_TEST_TONE;m++) {
  426. cc = (int)((thisfrq + halfchwidth)/chwidth);
  427. if((vc = cc)!=0)
  428. vc = cc * 2;
  429. if(vc != lastvc) {
  430. sampbuf[vc] = testpamp[m];
  431. sampbuf[vc+1] = (float)thisfrq;
  432. }
  433. lastvc = vc;
  434. if((thisfrq = thisfrq * 2.0) > nyquist) {
  435. post_totalamp = (double)totpamp[m];
  436. normalise(post_totalamp,pre_totalamp,wanted,sampbuf);
  437. ampadjusted = 1;
  438. break;
  439. }
  440. }
  441. if(!ampadjusted) {
  442. post_totalamp = (double)totpamp[PARTIALS_IN_TEST_TONE-1];
  443. normalise(post_totalamp,pre_totalamp,wanted,sampbuf);
  444. }
  445. }
  446. /******************************** NORMALISE ***************************/
  447. void normalise(double post_totalamp,double pre_totalamp,int wanted,float *sampbuf)
  448. {
  449. double normaliser;
  450. int vc;
  451. if(post_totalamp < VERY_TINY_AMP)
  452. return;
  453. normaliser = pre_totalamp/post_totalamp;
  454. for(vc = 0; vc < wanted; vc += 2) {
  455. if(sampbuf[vc] > 0.0f)
  456. sampbuf[vc] = (float)(sampbuf[vc] * normaliser);
  457. }
  458. }
  459. /****************************** HAMMING ******************************/
  460. void hamming(float *win,int winLen,int even)
  461. {
  462. float Pi,ftmp;
  463. int i;
  464. /***********************************************************
  465. Pi = (float)((double)4.*atan((double)1.));
  466. ***********************************************************/
  467. Pi = (float)PI;
  468. ftmp = Pi/winLen;
  469. if (even) {
  470. for (i=0; i<winLen; i++)
  471. *(win+i) = (float)((double).54 + (double).46*cos((double)(ftmp*((float)i+.5))));
  472. *(win+winLen) = 0.0f;}
  473. else{ *(win) = 1.0f;
  474. for (i=1; i<=winLen; i++)
  475. *(win+i) =(float)((double).54 + (double).46*cos((double)(ftmp*(float)i)));
  476. }
  477. return;
  478. }
  479. /****************************** FLOAT_ARRAY ******************************/
  480. int pvoc_float_array(int nnn,float **ptr)
  481. { /* set up a floating point array length nnn. */
  482. *ptr = (float *) calloc(nnn,sizeof(float));
  483. if(*ptr==NULL){
  484. fprintf(stdout,"ERROR: insufficient memory for PVOC\n");
  485. fflush(stdout);
  486. return(0);
  487. }
  488. return(1);
  489. }
  490. /****************************** PVOC_PROCESS_ADDON ******************************/
  491. int pvoc_process_addon(int ifd,int ofd,int chans,int origrate,float arate,int Mlen,int Dfac)
  492. {
  493. int num_overflows = 0;
  494. float *input, /* pointer to start of input buffer */
  495. *output, /* pointer to start of output buffer */
  496. *anal, /* pointer to start of analysis buffer */
  497. *syn, /* pointer to start of synthesis buffer */
  498. // *banal, /* pointer to anal[1] (for FFT calls) */
  499. *bsyn, /* pointer to syn[1] (for FFT calls) */
  500. // *nextIn, /* pointer to next empty word in input */
  501. *nextOut, /* pointer to next empty word in output */
  502. *analWindow, /* pointer to center of analysis window */
  503. *synWindow, /* pointer to center of synthesis window */
  504. *maxAmp, /* pointer to start of max amp buffer */
  505. *avgAmp, /* pointer to start of avg amp buffer */
  506. *avgFrq, /* pointer to start of avg frq buffer */
  507. *env, /* pointer to start of spectral envelope */
  508. *i0, /* pointer to amplitude channels */
  509. *i1, /* pointer to frequency channels */
  510. *oldInPhase, /* pointer to start of input phase buffer */
  511. *oldOutPhase, /* pointer to start of output phase buffer */
  512. maxsample = 0.0, minsample = 0.0;
  513. int M = 0, /* length of analWindow impulse response */
  514. D = 0, /* decimatin factor */
  515. I = 0, /* interpolation factor (default will be I=D)*/
  516. pvoc_chans = chans - 2,
  517. analWinLen, /* half-length of analysis window */
  518. synWinLen; /* half-length of synthesis window */
  519. int outCount, /* number of samples written to output */
  520. ibuflen, /* length of input buffer */
  521. obuflen, /* length of output buffer */
  522. nI = 0, /* current input (analysis) sample */
  523. nO, /* current output (synthesis) sample */
  524. nMaxOut; /* last output (synthesis) sample */
  525. int /* isr,*/ /* sampling rate */
  526. endsamp = VERY_BIG_INT;
  527. float mag, /* magnitude of analysis data */
  528. phase, /* phase of analysis data */
  529. // RoverTwoPi, /* R/D divided by 2*Pi */
  530. TwoPioverR, /* 2*Pi divided by R/I */
  531. F = (float)0, /* fundamental frequency (determines pvoc_chans) */
  532. sum, /* scale factor for renormalizing windows */
  533. // rIn, /* decimated sampling rate */
  534. rOut, /* pre-interpolated sampling rate */
  535. R; /* input sampling rate */
  536. int i,j,k, /* index variables */
  537. Dd, /* number of new inputs to read (Dd <= D) */
  538. Ii, /* number of new outputs to write (Ii <= I) */
  539. N2, /* pvoc_chans/2 */
  540. NO, /* synthesis NO = pvoc_chans / P */
  541. NO2, /* NO/2 */
  542. IO, /* synthesis IO = I / P */
  543. IOi, /* synthesis IOi = Ii / P */
  544. Mf = 0, /* flag for even M */
  545. #ifdef SINGLE_SAMP
  546. rv, /* return value from fgetfloat */
  547. #endif
  548. flag = 0; /* end-of-input flag */
  549. #if defined(__SC__) && defined(SOFT_FP)
  550. extern int _8087;
  551. _8087 = 0;
  552. #endif
  553. {
  554. char *mem;
  555. if((mem = malloc(64*SECSIZE)) == 0
  556. ||sndsetbuf(ifd, mem, 64) < 0) {
  557. fprintf(stdout, "ERROR: Can't set big input buffer for PVOC.\n");
  558. return(0);
  559. }
  560. }
  561. // isr = origrate;
  562. M = Mlen;
  563. D = Dfac;
  564. R = ((float) D * arate);
  565. if(flteq(R,0.0)) {
  566. fprintf(stdout, "ERROR: Problem: zero sampling rate in PVOC\n");
  567. return(0);
  568. }
  569. N2 = pvoc_chans / 2;
  570. F = (float)(R /(float)pvoc_chans);
  571. Mf = 1 - M%2;
  572. if (M < 7) {
  573. fprintf(stdout,"WARNING: analWindow impulse response is too small\n");
  574. fflush(stdout);
  575. }
  576. ibuflen = 4 * M;
  577. obuflen = 4 * M;
  578. I = D;
  579. NO = pvoc_chans; /* synthesis transform will be NO points */
  580. NO2 = NO/2;
  581. IO = I;
  582. /* set up analysis window: The window is assumed to be symmetric
  583. with M total points. After the initial memory allocation,
  584. analWindow always points to the midpoint of the window
  585. (or one half sample to the right, if M is even); analWinLen
  586. is half the true window length (rounded down). Any low pass
  587. window will work; a Hamming window is generally fine,
  588. but a Kaiser is also available. If the window duration is
  589. longer than the transform (M > N), then the window is
  590. multiplied by a sin(x)/x function to meet the condition:
  591. analWindow[Ni] = 0 for i != 0. In either case, the
  592. window is renormalized so that the phase vocoder amplitude
  593. estimates are properly scaled. The maximum allowable
  594. window duration is ibuflen/2. */
  595. if(!pvoc_float_array(M+Mf,&analWindow))
  596. return(0);
  597. analWindow += (analWinLen = M/2);
  598. hamming(analWindow,analWinLen,Mf);
  599. for (i = 1; i <= analWinLen; i++)
  600. *(analWindow - i) = *(analWindow + i - Mf);
  601. if (M > pvoc_chans) {
  602. if (Mf)
  603. *analWindow *=(float)
  604. ((double)pvoc_chans*sin((double)PI*.5/pvoc_chans)/(double)(PI*.5));
  605. for (i = 1; i <= analWinLen; i++)
  606. *(analWindow + i) *=(float)
  607. ((double)pvoc_chans * sin((double) (PI*(i+.5*Mf)/pvoc_chans) / (PI*(i+.5*Mf))));
  608. for (i = 1; i <= analWinLen; i++)
  609. *(analWindow - i) = *(analWindow + i - Mf);
  610. }
  611. sum = 0.0f;
  612. for (i = -analWinLen; i <= analWinLen; i++)
  613. sum += *(analWindow + i);
  614. sum = (float)(2.0/sum); /*factor of 2 comes in later in trig identity*/
  615. for (i = -analWinLen; i <= analWinLen; i++)
  616. *(analWindow + i) *= sum;
  617. /* set up synthesis window: For the minimal mean-square-error
  618. formulation (valid for N >= M), the synthesis window
  619. is identical to the analysis window (except for a
  620. scale factor), and both are even in length. If N < M,
  621. then an interpolating synthesis window is used. */
  622. if(!pvoc_float_array(M+Mf,&synWindow))
  623. return(0);
  624. synWindow += (synWinLen = M/2);
  625. if (M <= pvoc_chans){
  626. hamming(synWindow,synWinLen,Mf);
  627. for (i = 1; i <= synWinLen; i++)
  628. *(synWindow - i) = *(synWindow + i - Mf);
  629. for (i = -synWinLen; i <= synWinLen; i++)
  630. *(synWindow + i) *= sum;
  631. sum = 0.0f;
  632. for (i = -synWinLen; i <= synWinLen; i+=I)
  633. sum += *(synWindow + i) * *(synWindow + i);
  634. sum = (float)(1.0/ sum);
  635. for (i = -synWinLen; i <= synWinLen; i++)
  636. *(synWindow + i) *= sum;
  637. } else {
  638. hamming(synWindow,synWinLen,Mf);
  639. for (i = 1; i <= synWinLen; i++)
  640. *(synWindow - i) = *(synWindow + i - Mf);
  641. if (Mf)
  642. *synWindow *= (float)((double)IO * sin((double) (PI*.5/IO)) / (double)(PI*.5));
  643. for (i = 1; i <= synWinLen; i++)
  644. *(synWindow + i) *=(float)
  645. ((double)IO * sin((double) (PI*(i+.5*Mf)/IO)) /(double) (PI*(i+.5*Mf)));
  646. for (i = 1; i <= synWinLen; i++)
  647. *(synWindow - i) = *(synWindow + i - Mf);
  648. sum = (float)(1.0/sum);
  649. for (i = -synWinLen; i <= synWinLen; i++)
  650. *(synWindow + i) *= sum;
  651. }
  652. /* set up input buffer: nextIn always points to the next empty
  653. word in the input buffer (i.e., the sample following
  654. sample number (n + analWinLen)). If the buffer is full,
  655. then nextIn jumps back to the beginning, and the old
  656. values are written over. */
  657. if(!pvoc_float_array(ibuflen,&input))
  658. return(0);
  659. // nextIn = input;
  660. /* set up output buffer: nextOut always points to the next word
  661. to be shifted out. The shift is simulated by writing the
  662. value to the standard output and then setting that word
  663. of the buffer to zero. When nextOut reaches the end of
  664. the buffer, it jumps back to the beginning. */
  665. if(!pvoc_float_array(obuflen,&output))
  666. return(0);
  667. nextOut = output;
  668. /* set up analysis buffer for (N/2 + 1) channels: The input is real,
  669. so the other channels are redundant. oldInPhase is used
  670. in the conversion to remember the previous phase when
  671. calculating phase difference between successive samples. */
  672. if(!pvoc_float_array(pvoc_chans+2,&anal))
  673. return(0);
  674. // banal = anal + 1;
  675. if(!pvoc_float_array(N2+1,&oldInPhase))
  676. return(0);
  677. if(!pvoc_float_array(N2+1,&maxAmp))
  678. return(0);
  679. if(!pvoc_float_array(N2+1,&avgAmp))
  680. return(0);
  681. if(!pvoc_float_array(N2+1,&avgFrq))
  682. return(0);
  683. if(!pvoc_float_array(N2+1,&env))
  684. return(0);
  685. /* set up synthesis buffer for (pvoc_chans/2 + 1) channels: (This is included
  686. only for clarity.) oldOutPhase is used in the re-
  687. conversion to accumulate angle differences (actually angle
  688. difference per second). */
  689. if(!pvoc_float_array(NO+2,&syn))
  690. return(0);
  691. bsyn = syn + 1;
  692. if(!pvoc_float_array(NO2+1,&oldOutPhase))
  693. return(0);
  694. /* initialization: input time starts negative so that the rightmost
  695. edge of the analysis filter just catches the first non-zero
  696. input samples; output time is always T times input time. */
  697. outCount = 0;
  698. // rIn = (float)(R/(float)D);
  699. rOut = (float)(R/(float)I);
  700. // RoverTwoPi = (float)(rIn/TWOPI);
  701. TwoPioverR = (float)(TWOPI/rOut);
  702. nI = -(analWinLen / D) * D; /* input time (in samples) */
  703. nO = nI; /* output time (in samples) */
  704. Dd = analWinLen + nI + 1; /* number of new inputs to read */
  705. Ii = 0; /* number of new outputs to write */
  706. IOi = 0;
  707. flag = 1;
  708. /* main loop: If endsamp is not specified it is assumed to be very large
  709. and then readjusted when fgetfloat detects the end of input. */
  710. while(nI < (endsamp + analWinLen)){
  711. #ifdef SINGLE_SAMP
  712. for (i = 0; i < pvoc_chans+2; i++){ /* synthesis only */
  713. if ((rv = fgetfloat((anal+i),ifd)) <= 0){
  714. return 1;
  715. }
  716. }
  717. #else
  718. if((i = fgetfbufEx(anal, pvoc_chans+2, ifd,0)) < 0) {
  719. sfperror("pvoc: read error: ");
  720. return(0);
  721. }
  722. if(i < pvoc_chans+2)
  723. return 1;
  724. #endif
  725. /* reconversion: The magnitude and angle-difference-per-second in syn
  726. (assuming an intermediate sampling rate of rOut) are
  727. converted to real and imaginary values and are returned in syn.
  728. This automatically incorporates the proper phase scaling for
  729. time modifications. */
  730. if (NO <= pvoc_chans){
  731. for (i = 0; i < NO+2; i++)
  732. *(syn+i) = *(anal+i);
  733. } else {
  734. for (i = 0; i <= pvoc_chans+1; i++)
  735. *(syn+i) = *(anal+i);
  736. for (i = pvoc_chans+2; i < NO+2; i++)
  737. *(syn+i) = 0.0f;
  738. }
  739. for(i=0, i0=syn, i1=syn+1; i<= NO2; i++,i0+=2,i1+=2) {
  740. mag = *i0;
  741. *(oldOutPhase + i) += *i1 - ((float) i * F);
  742. phase = *(oldOutPhase + i) * TwoPioverR;
  743. *i0 = (float)((double)mag * cos((double)phase));
  744. *i1 = (float)((double)mag * sin((double)phase));
  745. }
  746. /* synthesis: The synthesis subroutine uses the Weighted Overlap-Add
  747. technique to reconstruct the time-domain signal. The (pvoc_chans/2 + 1)
  748. phase vocoder channel outputs at time n are inverse Fourier
  749. transformed, windowed, and added into the output array. The
  750. subroutine thinks of output as a shift register in which
  751. locations are referenced modulo obuflen. Therefore, the main
  752. program must take care to zero each location which it "shifts"
  753. out (to standard output). The subroutines reals and fft
  754. together perform an efficient inverse FFT. */
  755. if(reals_(syn,bsyn,NO2,2)<0) {
  756. fprintf(stdout,"ERROR: %s\n",errstr);
  757. fflush(stdout);
  758. return 0;
  759. }
  760. if(fft_(syn,bsyn,1,NO2,1,2)<0) {
  761. fprintf(stdout,"ERROR: %s\n",errstr);
  762. fflush(stdout);
  763. return 0;
  764. }
  765. j = nO - synWinLen - 1;
  766. while (j < 0)
  767. j += obuflen;
  768. j = j % obuflen;
  769. k = nO - synWinLen - 1;
  770. while (k < 0)
  771. k += NO;
  772. k = k % NO;
  773. for (i = -synWinLen; i <= synWinLen; i++) { /*overlap-add*/
  774. if (++j >= obuflen)
  775. j -= obuflen;
  776. if (++k >= NO)
  777. k -= NO;
  778. *(output + j) += *(syn + k) * *(synWindow + i);
  779. }
  780. #ifdef SINGLE_SAMP
  781. for (i = 0; i < IOi; i++) { /* shift out next IOi values */
  782. fputfloat(nextOut,ofd);
  783. *(nextOut++) = 0.;
  784. if (nextOut >= (output + obuflen))
  785. nextOut -= obuflen;
  786. outCount++;
  787. }
  788. #else
  789. for (i = 0; i < IOi;) { /* shift out next IOi values */
  790. int jj;
  791. int todo = min(IOi-i, output+obuflen-nextOut);
  792. if(!outfloats(nextOut,&maxsample,&minsample,&num_overflows,todo, ofd))
  793. return(0);
  794. i += todo;
  795. outCount += todo;
  796. for(jj = 0; jj < todo; jj++)
  797. *nextOut++ = 0.0f;
  798. if (nextOut >= (output + obuflen))
  799. nextOut -= obuflen;
  800. }
  801. #endif
  802. if(flag /* flag means do this operation only once */
  803. && (nI > 0) && (Dd < D)) { /* EOF detected */
  804. flag = 0;
  805. endsamp = nI + analWinLen - (D - Dd);
  806. }
  807. nI += D; /* increment time */
  808. nO += IO;
  809. /* Dd = D except when the end of the sample stream intervenes */
  810. Dd = min(D, max(0, D+endsamp-nI-analWinLen));
  811. if (nO > (synWinLen + I))
  812. Ii = I;
  813. else if (nO > synWinLen)
  814. Ii = nO - synWinLen;
  815. else {
  816. Ii = 0;
  817. for (i=nO+synWinLen; i<obuflen; i++) {
  818. if (i > 0)
  819. *(output+i) = 0.0f;
  820. }
  821. }
  822. IOi = Ii;
  823. } /* End of main while loop */
  824. nMaxOut = endsamp;
  825. while (outCount <= nMaxOut){
  826. #ifdef SINGLE_SAMP
  827. outCount++;
  828. fputfloat(nextOut++,ofd);
  829. if (nextOut >= (output + obuflen))
  830. nextOut -= obuflen;
  831. #else
  832. int todo = min(nMaxOut-outCount, output+obuflen-nextOut);
  833. if(todo == 0)
  834. break;
  835. if(!outfloats(nextOut,&maxsample,&minsample,&num_overflows,todo, ofd))
  836. return(0);
  837. outCount += todo;
  838. nextOut += todo;
  839. if (nextOut >= (output + obuflen))
  840. nextOut -= obuflen;
  841. #endif
  842. }
  843. return(1);
  844. }
  845. /************************************ OUTFLOATS ************************************
  846. *TW 2002 no longer need to do conversion to floats: this func is now just checking for clipping
  847. *
  848. * ORIGINALLY (MCA) Converted floats -> shorts explicitly, since we are compiled with
  849. * hardware FP(probably), and the sound filing system is not!
  850. * (even without this, it should be more efficient!)
  851. */
  852. int outfloats(float *nextOut,float *maxsample,float *minsample,int *num_overflows,int todo, int ofd)
  853. {
  854. static float *sbuf = 0;
  855. static int sblen = 0;
  856. float *sp;
  857. int cnt;
  858. float val;
  859. if(sblen < todo) {
  860. if(sbuf != 0)
  861. free(sbuf);
  862. if((sbuf = (float *)malloc(todo*sizeof(float))) == 0) {
  863. fprintf(stdout, "ERROR: PVOC can't allocate output buffer\n");
  864. fflush(stdout);
  865. return(0);
  866. }
  867. sblen = todo;
  868. }
  869. sp = sbuf;
  870. #ifdef NOOVERCHK
  871. for(cnt = 0; cnt < todo; cnt++)
  872. *sp++ = *nextOut++;
  873. #else
  874. for(cnt = 0; cnt < todo; cnt++) {
  875. val = *nextOut++;
  876. if(val >= 1.0 || val <= -1.0) {
  877. (*num_overflows)++;
  878. if(val > 0.0f) {
  879. if(val > *maxsample)
  880. *maxsample = val;
  881. val = 1.0f;
  882. }
  883. if(val < 0.0f) {
  884. if(val < *minsample)
  885. *minsample = val;
  886. val = -1.0f;
  887. }
  888. }
  889. *sp++ = val;
  890. }
  891. #endif
  892. if(fputfbufEx(sbuf, todo, ofd) < todo) {
  893. fprintf(stdout,"ERROR: PVOC write error");
  894. fflush(stdout);
  895. return(0);
  896. }
  897. return(1);
  898. }
  899. /**************************** PRESET_SAMPBUF ******************************
  900. *
  901. * Preset all frqs to centre of channels.
  902. */
  903. void preset_sampbuf(float *sampbuf,double halfchwidth, int clength, float *chbot)
  904. {
  905. int cc, vc , clength_less_1 = clength -1;
  906. sampbuf[1] = (float)(halfchwidth/2.0);
  907. for(cc = 1, vc = 2; cc < clength_less_1; cc++, vc += 2)
  908. sampbuf[vc+1] = (float)(chbot[cc] + halfchwidth);
  909. sampbuf[vc+1]=(float)(chbot[clength_less_1]+(halfchwidth/2.0));
  910. }
  911. /**************************** FLTEQ *******************************/
  912. int flteq(double f1,double f2)
  913. { double upperbnd, lowerbnd;
  914. upperbnd = f2 + FLTERR;
  915. lowerbnd = f2 - FLTERR;
  916. if((f1>upperbnd) || (f1<lowerbnd))
  917. return(0);
  918. return(1);
  919. }