formantsg.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. /*
  2. * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. /* floatsam version */
  22. /* Sept 05: TW fix for formants put */
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <memory.h>
  26. #include <string.h>
  27. #include <structures.h>
  28. #include <tkglobals.h>
  29. #include <globcon.h>
  30. #include <filetype.h>
  31. #include <formants.h>
  32. #include <speccon.h>
  33. #include <sfsys.h>
  34. #define round(x) lround((x))
  35. #define CHAN_SRCHRANGE_F (4)
  36. static int set_specenv_frqs(int arraycnt,dataptr dz);
  37. static int setup_octaveband_steps(double **interval,dataptr dz);
  38. static int setup_low_octave_bands(int arraycnt,dataptr);
  39. /************************** INITIALISE_SPECENV *********************
  40. *
  41. * MAR 1998: not sure if the follwoing comment is relevant any more
  42. * but I wont risk changing it at this stage.
  43. *
  44. * WANTED and CLENGTH are calculated from scratch here, as dz->wanted
  45. * gets set equal to dz->specenvcnt for calculations on formant data,
  46. * while dz->clength may not yet be set!!
  47. */
  48. int initialise_specenv(int *arraycnt,dataptr dz)
  49. {
  50. int wanted,clength;
  51. switch(dz->infile->filetype) {
  52. case(ANALFILE):
  53. wanted = dz->infile->channels;
  54. break;
  55. case(FORMANTFILE):
  56. case(PITCHFILE):
  57. case(TRANSPOSFILE):
  58. wanted = dz->infile->origchans;
  59. break;
  60. default:
  61. sprintf(errstr,"Unknown original filetype: initialise_specenv()\n");
  62. return(PROGRAM_ERROR);
  63. }
  64. clength = wanted/2;
  65. *arraycnt = clength + 1;
  66. if((dz->specenvfrq = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
  67. sprintf(errstr,"INSUFFICIENT MEMORY for formant frq array.\n");
  68. return(MEMORY_ERROR);
  69. }
  70. if((dz->specenvpch = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
  71. sprintf(errstr,"INSUFFICIENT MEMORY for formant pitch array.\n");
  72. return(MEMORY_ERROR);
  73. }
  74. /*RWD zero the data */
  75. memset(dz->specenvpch,0,*arraycnt * sizeof(float));
  76. if((dz->specenvamp = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
  77. sprintf(errstr,"INSUFFICIENT MEMORY for formant aplitude array.\n");
  78. return(MEMORY_ERROR);
  79. }
  80. if((dz->specenvtop = (float *)malloc((*arraycnt) * sizeof(float)))==NULL) {
  81. sprintf(errstr,"INSUFFICIENT MEMORY for formant frq limit array.\n");
  82. return(MEMORY_ERROR);
  83. }
  84. return(FINISHED);
  85. }
  86. /************************** READ_FORMANTBAND_DATA_AND_SETUP_FORMANTS *********************/
  87. int read_formantband_data_and_setup_formants(char ***cmdline,int *cmdlinecnt,dataptr dz)
  88. {
  89. int exit_status;
  90. int max_fbands = 0, arraycnt;
  91. aplptr ap = dz->application;
  92. if((exit_status = establish_formant_band_ranges(dz->infile->channels,ap))<0)
  93. return(exit_status);
  94. if(!sloom) {
  95. if(strlen((*cmdline)[0])<3) {
  96. sprintf(errstr,"Formant parameter missing on cmdline.\n");
  97. return(USAGE_ONLY);
  98. }
  99. if(!strncmp((*cmdline)[0],"-f",2))
  100. dz->specenv_type = FREQWISE_FORMANTS;
  101. else if(!strncmp((*cmdline)[0],"-p",2))
  102. dz->specenv_type = PICHWISE_FORMANTS;
  103. else {
  104. sprintf(errstr,"Formant flag missing on cmdline.\n");
  105. return(USAGE_ONLY);
  106. }
  107. if(dz->specenv_type==PICHWISE_FORMANTS && ap->no_pitchwise_formants) {
  108. sprintf(errstr,"-p flag can't be used: Too few analysis data channels.\n");
  109. return(DATA_ERROR);
  110. }
  111. (*cmdline)[0] += 2;
  112. if(sscanf((*cmdline)[0],"%d",&(dz->formant_bands))!=1) {
  113. sprintf(errstr,"Cannot read count of formant_bands.\n");
  114. return(USAGE_ONLY);
  115. }
  116. (*cmdline)++;
  117. (*cmdlinecnt)--;
  118. } else {
  119. if((*cmdline)[0][0]!=NUMERICVAL_MARKER) { /* TK convention, values are preceded by '@' */
  120. sprintf(errstr,"Invalid value for Formant bands switch sent from TK\n");
  121. return(DATA_ERROR);
  122. }
  123. ((*cmdline)[0])++;
  124. switch((*cmdline)[0][0]) {
  125. case('0'): dz->specenv_type = PICHWISE_FORMANTS; break;
  126. case('1'): dz->specenv_type = FREQWISE_FORMANTS; break;
  127. default:
  128. sprintf(errstr,"Bad value (%c) for Formant Flag sent from TK\n",((*cmdline)[0][0]));
  129. return(DATA_ERROR);
  130. }
  131. (*cmdline)++;
  132. (*cmdlinecnt)--;
  133. if((*cmdline)[0][0]!=NUMERICVAL_MARKER) { /* TK convention, values are preceded by '@' */
  134. sprintf(errstr,"Invalid value for Formant bands sent from TK\n");
  135. return(DATA_ERROR);
  136. }
  137. ((*cmdline)[0])++;
  138. if(sscanf((*cmdline)[0],"%d",&(dz->formant_bands))!=1) {
  139. sprintf(errstr,"No formant band count sent from TK.\n");
  140. return(USAGE_ONLY);
  141. }
  142. (*cmdline)++;
  143. (*cmdlinecnt)--;
  144. }
  145. switch(dz->specenv_type) {
  146. case(PICHWISE_FORMANTS): max_fbands = ap->max_pichwise_fbands; break;
  147. case(FREQWISE_FORMANTS): max_fbands = ap->max_freqwise_fbands; break;
  148. }
  149. if(dz->formant_bands < ap->min_fbands) {
  150. sprintf(errstr,"Too few formant_bands requested: min for this file is %d\n",ap->min_fbands);
  151. return(DATA_ERROR);
  152. }
  153. if(dz->formant_bands > max_fbands) {
  154. sprintf(errstr,"Too many formant_bands requested: max for this file is %d\n",max_fbands);
  155. return(DATA_ERROR);
  156. }
  157. if((exit_status = initialise_specenv(&arraycnt,dz))<0)
  158. return(exit_status);
  159. if((exit_status = set_specenv_frqs(arraycnt,dz))<0)
  160. return(exit_status);
  161. dz->descriptor_samps = dz->infile->specenvcnt * DESCRIPTOR_DATA_BLOKS ;
  162. return(FINISHED);
  163. }
  164. /************************ SET_SPECENV_FRQS ************************
  165. *
  166. * FREQWISE BANDS = number of channels for each specenv point
  167. * PICHWISE BANDS = number of points per octave
  168. */
  169. int set_specenv_frqs(int arraycnt,dataptr dz)
  170. {
  171. int exit_status;
  172. double frqstep, thisfrq, nextfrq, bandbot;
  173. double *interval;
  174. int m, n, k = 0, cc;
  175. switch(dz->specenv_type) {
  176. case(FREQWISE_FORMANTS):
  177. dz->specenvamp[0] = (float)0.0;
  178. dz->specenvfrq[0] = (float)1.0;
  179. dz->specenvpch[0] = (float)log10(dz->specenvfrq[0]);
  180. dz->specenvtop[0] = (float)dz->halfchwidth;
  181. frqstep = dz->halfchwidth * (double)dz->formant_bands;
  182. thisfrq = dz->specenvtop[0];
  183. k = 1;
  184. while((nextfrq = thisfrq + frqstep) < dz->nyquist) {
  185. if(k >= arraycnt) {
  186. sprintf(errstr,"Formant array too small: set_specenv_frqs()\n");
  187. return(PROGRAM_ERROR);
  188. }
  189. dz->specenvfrq[k] = (float)nextfrq;
  190. dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
  191. nextfrq += frqstep;
  192. dz->specenvtop[k] = (float)min(dz->nyquist,nextfrq);
  193. thisfrq = nextfrq;
  194. k++;
  195. }
  196. break;
  197. case(PICHWISE_FORMANTS):
  198. if((exit_status = setup_octaveband_steps(&interval,dz))<0)
  199. return(exit_status);
  200. if((exit_status = setup_low_octave_bands(arraycnt,dz))<0)
  201. return(exit_status);
  202. k = TOP_OF_LOW_OCTAVE_BANDS;
  203. cc = CHAN_ABOVE_LOW_OCTAVES;
  204. while(cc <= dz->clength) {
  205. m = 0;
  206. if((bandbot = dz->chwidth * (double)cc) >= dz->nyquist)
  207. break;
  208. for(n=0;n<dz->formant_bands;n++) {
  209. if(k >= arraycnt) {
  210. sprintf(errstr,"Formant array too small: set_specenv_frqs()\n");
  211. return(PROGRAM_ERROR);
  212. }
  213. dz->specenvfrq[k] = (float)(bandbot * interval[m++]);
  214. dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
  215. dz->specenvtop[k++] = (float)(bandbot * interval[m++]);
  216. }
  217. cc *= 2; /* 8-16: 16-32: 32-64 etc as 8vas, then split into bands */
  218. }
  219. break;
  220. }
  221. dz->specenvfrq[k] = (float)dz->nyquist;
  222. dz->specenvpch[k] = (float)log10(dz->nyquist);
  223. dz->specenvtop[k] = (float)dz->nyquist;
  224. dz->specenvamp[k] = (float)0.0;
  225. k++;
  226. dz->infile->specenvcnt = k;
  227. return(FINISHED);
  228. }
  229. /************************* SETUP_OCTAVEBAND_STEPS ************************/
  230. int setup_octaveband_steps(double **interval,dataptr dz)
  231. {
  232. double octave_step;
  233. int n = 1, m = 0, halfbands_per_octave = dz->formant_bands * 2;
  234. if((*interval = (double *)malloc(halfbands_per_octave * sizeof(double)))==NULL) {
  235. sprintf(errstr,"INSUFFICIENT MEMORY establishing interval array for formants.\n");
  236. return(MEMORY_ERROR);
  237. }
  238. while(n < halfbands_per_octave) {
  239. octave_step = (double)n++/(double)halfbands_per_octave;
  240. (*interval)[m++] = pow(2.0,octave_step);
  241. }
  242. (*interval)[m] = 2.0;
  243. return(FINISHED);
  244. }
  245. /************************ SETUP_LOW_OCTAVE_BANDS ***********************
  246. *
  247. * Lowest PVOC channels span larger freq steps and therefore we must
  248. * group them in octave bands, rather than in anything smaller.
  249. */
  250. int setup_low_octave_bands(int arraycnt,dataptr dz)
  251. {
  252. int n;
  253. if(arraycnt < LOW_OCTAVE_BANDS) {
  254. sprintf(errstr,"Insufficient array space for low_octave_bands\n");
  255. return(PROGRAM_ERROR);
  256. }
  257. for(n=0;n<LOW_OCTAVE_BANDS;n++) {
  258. switch(n) {
  259. case(0):
  260. dz->specenvfrq[0] = (float)1.0; /* frq whose log is 0 */
  261. dz->specenvpch[0] = (float)0.0;
  262. dz->specenvtop[0] = (float)dz->chwidth; /* 8VA wide bands */
  263. break;
  264. case(1):
  265. dz->specenvfrq[1] = (float)(dz->chwidth * 1.5); /* Centre Chs 1-2 */
  266. dz->specenvpch[1] = (float)log10(dz->specenvfrq[1]);
  267. dz->specenvtop[1] = (float)(dz->chwidth * 2.0);
  268. break;
  269. case(2):
  270. dz->specenvfrq[2] = (float)(dz->chwidth * 3.0); /* Centre Chs 2-4 */
  271. dz->specenvpch[2] = (float)log10(dz->specenvfrq[2]);
  272. dz->specenvtop[2] = (float)(dz->chwidth * 4.0);
  273. break;
  274. case(3):
  275. dz->specenvfrq[3] = (float)(dz->chwidth * 6.0); /* Centre Chs 4-8 */
  276. dz->specenvpch[3] = (float)log10(dz->specenvfrq[3]);
  277. dz->specenvtop[3] = (float)(dz->chwidth * 8.0);
  278. break;
  279. default:
  280. sprintf(errstr,"Insufficient low octave band setups in setup_low_octave_bands()\n");
  281. return(PROGRAM_ERROR);
  282. }
  283. }
  284. return(FINISHED);
  285. }
  286. /**************************** GETSPECENVAMP *************************/
  287. int getspecenvamp(double *thisamp,double thisfrq,int storeno,dataptr dz)
  288. {
  289. double pp, ratio, ampdiff;
  290. float *ampstore;
  291. int z = 1;
  292. if(thisfrq<0.0) { /* NOT SURE THIS IS CORRECT */
  293. *thisamp = 0.0; /* SHOULD WE PHASE INVERT & RETURN A -ve AMP ?? */
  294. return(FINISHED);
  295. }
  296. if(thisfrq<=1.0)
  297. pp = 0.0;
  298. else
  299. pp = log10(thisfrq);
  300. while( dz->specenvpch[z] < pp){
  301. z++;
  302. /*RWD may need to trap on size of array? */
  303. if(z == dz->infile->specenvcnt -1)
  304. break;
  305. }
  306. switch(storeno) {
  307. case(0):
  308. ampstore = dz->specenvamp; break;
  309. case(1):
  310. ampstore = dz->specenvamp2; break;
  311. default:
  312. sprintf(errstr,"Unknown storenumber in getspecenvamp()\n");
  313. return(PROGRAM_ERROR);
  314. }
  315. ratio = (pp - dz->specenvpch[z-1])/(dz->specenvpch[z] - dz->specenvpch[z-1]);
  316. ampdiff = ampstore[z] - ampstore[z-1];
  317. *thisamp = ampstore[z-1] + (ampdiff * ratio);
  318. *thisamp = max(0.0,*thisamp);
  319. return(FINISHED);
  320. }
  321. /********************** EXTRACT_SPECENV *******************/
  322. int extract_specenv(int bufptr_no,int storeno,dataptr dz) /* bufptr_no = flbufptr number (usually 0) */
  323. {
  324. int n, cc, vc, specenvcnt_less_one;
  325. int botchan, topchan;
  326. double botfreq, topfreq;
  327. double bwidth_in_chans;
  328. float *ampstore;
  329. switch(storeno) {
  330. case(0): ampstore = dz->specenvamp; break;
  331. case(1): ampstore = dz->specenvamp2; break;
  332. default:
  333. sprintf(errstr,"Unknown storenumber in extract_specenv()\n");
  334. return(PROGRAM_ERROR);
  335. }
  336. specenvcnt_less_one = dz->infile->specenvcnt - 1;
  337. vc = 0;
  338. switch(dz->deal_with_chan_data) {
  339. case(RECTIFY_CHANNEL_FRQ_ORDER):
  340. for(n=0;n<dz->infile->specenvcnt;n++)
  341. ampstore[n] = (float)0.0;
  342. topfreq = 0.0f;
  343. n = 0;
  344. while(n < specenvcnt_less_one) {
  345. botfreq = topfreq;
  346. botchan = (int)((botfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  347. botchan -= CHAN_SRCHRANGE_F;
  348. botchan = max(botchan,0);
  349. topfreq = dz->specenvtop[n];
  350. topchan = (int)((topfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  351. topchan += CHAN_SRCHRANGE_F;
  352. topchan = min(topchan,dz->clength);
  353. for(cc = botchan,vc = botchan * 2; cc < topchan; cc++,vc += 2) {
  354. if(dz->flbufptr[bufptr_no][FREQ] >= botfreq && dz->flbufptr[bufptr_no][FREQ] < topfreq)
  355. ampstore[n] = (float)(ampstore[n] + dz->flbufptr[bufptr_no][AMPP]);
  356. }
  357. bwidth_in_chans = (double)(topfreq - botfreq)/dz->chwidth;
  358. ampstore[n] = (float)(ampstore[n]/bwidth_in_chans);
  359. n++;
  360. }
  361. break;
  362. case(IGNORE_ACTUAL_CHAN_FRQS):
  363. for(n=1;n<specenvcnt_less_one;n++)
  364. ampstore[n] = (float)0.0;
  365. ampstore[0] = (float)(dz->flbufptr[bufptr_no][0]/2.0); /* dz->halfchwidth WIDE CHANNEL */
  366. cc = 1;
  367. vc = 2;
  368. n = 1; /* OMIT LOWEST CHANNEL */
  369. topfreq = dz->halfchwidth;
  370. while(cc < dz->clength && n < specenvcnt_less_one) {
  371. botfreq = topfreq;
  372. topfreq += dz->chwidth;
  373. if(topfreq < dz->specenvtop[n]) {
  374. if(botfreq >= dz->specenvtop[n-1]) /* WHOLLY IN SPECENVBAND */
  375. ampstore[n]=(float)(ampstore[n] + dz->flbufptr[bufptr_no][AMPP]);
  376. else /* PARTLY IN SPECENVBAND */
  377. ampstore[n]=(float)(ampstore[n]+(dz->flbufptr[bufptr_no][AMPP]/2.0));
  378. cc++;
  379. vc += 2;
  380. } else if(botfreq < dz->specenvtop[n]) { /* PARTLY IN SPECENVBAND */
  381. ampstore[n]=(float)(ampstore[n] + (dz->flbufptr[bufptr_no][AMPP]/2.0));
  382. cc++;
  383. vc += 2;
  384. } else { /* NOT IN SPECENVBAND */
  385. bwidth_in_chans = (dz->specenvtop[n]-dz->specenvtop[n-1])/dz->chwidth;
  386. ampstore[n] = (float)(ampstore[n]/bwidth_in_chans);
  387. n++; /* GO TO NEXT SPECENVBAND */
  388. }
  389. }
  390. break;
  391. case(NOT_SET): //RWD: add default action too...
  392. sprintf(errstr,"DEAL_WITH_CHAN_DATA flag not set in extract_specenv()\n");
  393. return(PROGRAM_ERROR);
  394. }
  395. return(FINISHED);
  396. }
  397. /********************* EXTRACT_SPECENV_OVER_PARTIALS ***********************/
  398. int extract_specenv_over_partials(int *specenvcnt,double thispitch,int bufptr_no,dataptr dz)
  399. { /* bufptr_no = flbufptr number (usually 0) */
  400. int exit_status;
  401. int n = 0, k, cc, vc, lastk = 0;
  402. for(n=0;n<=dz->clength;n++)
  403. dz->specenvamp[n] = 0.0F;
  404. n = 0;
  405. dz->specenvfrq[n] = 1.0F;
  406. dz->specenvpch[n++] = 0.0F;
  407. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  408. if((exit_status = is_harmonic(&k,dz->flbufptr[bufptr_no][FREQ],thispitch))<0)
  409. return(exit_status);
  410. if(exit_status==FALSE)
  411. continue;
  412. if(k==lastk) {
  413. if(dz->flbufptr[bufptr_no][AMPP] > dz->specenvamp[n]) {
  414. dz->specenvamp[n] = dz->flbufptr[bufptr_no][AMPP]; /* GET LOUDEST PARTIAL */
  415. dz->specenvfrq[n] = (float)max(1.0f,dz->flbufptr[bufptr_no][FREQ]); /* NEAR HARMONIC */
  416. dz->specenvpch[n] = (float)log10(dz->specenvfrq[n]);
  417. }
  418. } else {
  419. n++;
  420. dz->specenvamp[n] = dz->flbufptr[bufptr_no][AMPP]; /* KEEP AMP & FRQ OF PARTIAL */
  421. dz->specenvfrq[n] = (float)max(1.0f,dz->flbufptr[bufptr_no][FREQ]);
  422. dz->specenvpch[n] = (float)log10(dz->specenvfrq[n]);
  423. lastk = k;
  424. }
  425. }
  426. n++;
  427. dz->specenvamp[n] = 0.0F;
  428. dz->specenvfrq[n] = (float)dz->nyquist;
  429. dz->specenvpch[n] = (float)log10(dz->specenvfrq[n]);
  430. n++;
  431. *specenvcnt = n;
  432. return(FINISHED);
  433. }
  434. /**************************** IS_HARMONIC *************************
  435. *
  436. * WARNING: Checks if FIRST FREQ is harmonic of 2nd: NOT VICE VERSA!!
  437. */
  438. int is_harmonic(int *iratio,double frq1, double frq2)
  439. {
  440. double ratio, intvl;
  441. if(frq2 < FLTERR) {
  442. sprintf(errstr,"Zero frequency submitted as fundamental to is_harmonic()\n");
  443. return(PROGRAM_ERROR);
  444. }
  445. ratio = frq1/frq2;
  446. *iratio = round(ratio);
  447. if(ratio > *iratio)
  448. intvl = ratio/(double)(*iratio);
  449. else
  450. intvl = (double)(*iratio)/ratio;
  451. if(intvl > SEMITONE_INTERVAL)
  452. return(FALSE);
  453. return(TRUE);
  454. }
  455. /************************** INITIALISE_SPECENV2 *********************/
  456. int initialise_specenv2(dataptr dz)
  457. {
  458. int wanted,clength;
  459. int n;
  460. switch(dz->infile->filetype) {
  461. case(ANALFILE):
  462. wanted = dz->infile->channels;
  463. break;
  464. case(FORMANTFILE):
  465. case(PITCHFILE):
  466. case(TRANSPOSFILE):
  467. wanted = dz->infile->origchans;
  468. break;
  469. default:
  470. sprintf(errstr,"Unknown original filetype: initialise_specenv2()\n");
  471. return(PROGRAM_ERROR);
  472. }
  473. clength = wanted/2;
  474. if((dz->specenvamp2 = (float *)malloc((clength+1) * sizeof(float)))==NULL) {
  475. sprintf(errstr,"INSUFFICIENT MEMORY for second formant amplitude array.\n");
  476. return(MEMORY_ERROR);
  477. }
  478. for(n=0;n<dz->infile->specenvcnt;n++)
  479. dz->specenvamp2[n] = 0.0f;
  480. return(FINISHED);
  481. }
  482. /******************** WRITE_FORMANT_DESCRIPTOR **********************/
  483. int write_formant_descriptor(float **fptr1,float *fptr2,dataptr dz)
  484. {
  485. int fsamps_to_write = dz->descriptor_samps/DESCRIPTOR_DATA_BLOKS;
  486. *fptr1 = fptr2;
  487. memmove((char *)(*fptr1),(char *)dz->specenvpch,(size_t)(fsamps_to_write * sizeof(float)));
  488. *fptr1 += dz->infile->specenvcnt;
  489. memmove((char *)(*fptr1),(char *)dz->specenvtop,(size_t)(fsamps_to_write * sizeof(float)));
  490. *fptr1 += dz->infile->specenvcnt;
  491. return(FINISHED);
  492. }
  493. /******************** SETUP_FORMANT_PARAMS **********************/
  494. int setup_formant_params(int fd,dataptr dz)
  495. {
  496. int samps_read;
  497. /*RWD what the f**** are these? */
  498. int fsamps_to_read = dz->descriptor_samps/DESCRIPTOR_DATA_BLOKS;
  499. /*RWD need dz->bigbuflen2 ? */
  500. if(dz->buflen2 <= 0) {
  501. // sprintf(errstr,"bigbufsize2 not established: setup_formant_params()\n");
  502. sprintf(errstr,"buflen2 not established: setup_formant_params()\n");
  503. return(PROGRAM_ERROR);
  504. }
  505. if(dz->buflen2 < dz->descriptor_samps) {
  506. // sprintf(errstr,"bigbufsize2 smaller than descriptor_samps: setup_formant_params()\n");
  507. sprintf(errstr,"buflen2 smaller than descriptor_samps: setup_formant_params()\n");
  508. return(PROGRAM_ERROR);
  509. }
  510. if((samps_read = fgetfbufEx(dz->flbufptr[2], dz->buflen2,fd,0)) < dz->descriptor_samps) {
  511. if(samps_read<0) {
  512. sprintf(errstr,"Sound read error.\n");
  513. return(SYSTEM_ERROR);
  514. }
  515. sprintf(errstr,"No data in formantfile.\n");
  516. return(DATA_ERROR);
  517. }
  518. /*TW Sept 05*/
  519. dz->ssampsread = samps_read;
  520. dz->flbufptr[1] = dz->flbufptr[2];
  521. memmove((char *)dz->specenvpch,(char *)dz->flbufptr[1],(size_t)(fsamps_to_read * sizeof(float)));
  522. dz->flbufptr[1] += dz->infile->specenvcnt;
  523. memmove((char *)dz->specenvtop,(char *)dz->flbufptr[1],(size_t)(fsamps_to_read * sizeof(float)));
  524. dz->flbufptr[1] += dz->infile->specenvcnt;
  525. return(FINISHED);
  526. }
  527. /****************************** EXTRACT_FORMANT_PEAKS2 ***************************/
  528. int extract_formant_peaks2(int sl1param,int *thispkcnt,double lofrq_limit,double hifrq_limit,dataptr dz)
  529. {
  530. int n;
  531. int falling = 0, last_channel_was_in_range = 1;
  532. int *fppk = dz->stable->fpk[dz->iparam[sl1param]];
  533. *thispkcnt = 0;
  534. n = 1;
  535. while(n<dz->infile->specenvcnt) {
  536. if(dz->specenvfrq[n] < lofrq_limit) {
  537. last_channel_was_in_range = 0;
  538. n++;
  539. continue;
  540. }
  541. if(dz->specenvamp[n] > dz->specenvamp[n-1])
  542. falling = 0;
  543. else {
  544. if(!falling) {
  545. if(last_channel_was_in_range)
  546. fppk[(*thispkcnt)++] = n-1;
  547. falling = 1;
  548. }
  549. }
  550. last_channel_was_in_range = 1;
  551. if(dz->specenvfrq[n] > hifrq_limit)
  552. break;
  553. n++;
  554. }
  555. return(FINISHED);
  556. }