pitch.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  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. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <pnames.h>
  24. #include <structures.h>
  25. #include <tkglobals.h>
  26. #include <globcon.h>
  27. #include <modeno.h>
  28. #include <arrays.h>
  29. #include <flags.h>
  30. #include <pitch.h>
  31. #include <cdpmain.h>
  32. #include <formants.h>
  33. #include <speccon.h>
  34. #include <sfsys.h>
  35. #include <pitch.h>
  36. #include <memory.h>
  37. #define round(x) lround((x))
  38. static int do_spectral_shiftp(dataptr dz);
  39. static int replace_partial_by_tuned_partial(int cc,int vc,dataptr dz);
  40. static int focus_partial_towards_tuned_value(int vc, int cc,dataptr dz);
  41. static int gotnewfrq(int *newvc,int vc,double *thisamp,double *thisfrq, double thisspecamp,int n, dataptr dz);
  42. static int gotnewfrq2(int *newvc,int vc,double *thisamp,double *thisfrq,int n, dataptr dz);
  43. static int remove_unwanted_frq_areas(double lofrq_limit,double hifrq_limit,dataptr dz);
  44. /********************************** SPECALT **********************************/
  45. int specalt(int *pitchcnt,dataptr dz)
  46. {
  47. int n = 1, cc, vc;
  48. int exit_status; /* RWD: for specbare() retval ! */
  49. double pitch;
  50. if((exit_status = specbare(pitchcnt,dz))<0)
  51. return exit_status;
  52. (*pitchcnt)--;
  53. pitch = dz->pitches[(*pitchcnt)++];
  54. if(pitch < 0.0) /* UNPITCHED WINDOW : IGNORE */
  55. return(FINISHED);
  56. switch(dz->mode) {
  57. case(DELETE_ODD):
  58. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  59. if(dz->flbufptr[0][vc]>0.0) {
  60. if(ODD(n))
  61. dz->flbufptr[0][vc] = 0.0F;
  62. n++;
  63. }
  64. }
  65. break;
  66. case(DELETE_EVEN):
  67. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  68. if(dz->flbufptr[0][vc]>0.0) {
  69. if(EVEN(n))
  70. dz->flbufptr[0][vc] = 0.0F;
  71. n++;
  72. }
  73. }
  74. break;
  75. default:
  76. sprintf(errstr,"Invalid option in specalt()\n");
  77. return(PROGRAM_ERROR);
  78. break;
  79. }
  80. return(FINISHED);
  81. }
  82. /**************************** SPECOCT ****************************
  83. *
  84. * (1) TRANSPOSE UPWARDS.
  85. * (a) Delete all channels that are NOT harmonics.
  86. * (b) Delete all harmonics that are not EVEN (or *3 or *4 etc) harmonics.
  87. * (2) TRANSPOSE DOWNWARDS.
  88. * Insert harmonics below and between the original fundamental and harmonics.
  89. */
  90. int specoct(dataptr dz)
  91. {
  92. int exit_status;
  93. double pre_totalamp, post_totalamp, thisfrq, basefrq, baseamp, thisamp;
  94. int n, specenvcnt, vc, truecc, truevc;
  95. if((thisfrq = dz->pitches[dz->total_windows]) <= 0.0)
  96. return(FINISHED);
  97. if((exit_status = get_totalamp(&pre_totalamp,dz->flbufptr[0],dz->wanted))<0)
  98. return(exit_status);
  99. switch(dz->mode) {
  100. case(OCT_UP): /* UPWARDS: DELETING ALTERNATE HARMONICS */
  101. thisfrq *= (double)dz->iparam[OCT_HMOVE];
  102. for(vc = 0; vc < dz->wanted; vc += 2) {
  103. if((exit_status = is_harmonic(&n,(double)dz->flbufptr[0][FREQ],thisfrq))<0)
  104. return(exit_status);
  105. if(exit_status==FALSE)
  106. dz->flbufptr[0][AMPP] = 0.0f;
  107. }
  108. break;
  109. case(OCT_DN): /* DNWARDS: INSERT INTERVENING HARMONICS */
  110. case(OCT_DN_BASS): /* DITTO WITH BASS REINFORCE */
  111. if((exit_status = extract_specenv_over_partials(&specenvcnt,thisfrq,0,dz))<0)
  112. return(exit_status);
  113. basefrq = thisfrq/(double)dz->iparam[OCT_HMOVE];
  114. if((exit_status = getspecenvamp(&baseamp,basefrq,0,dz))<0)
  115. return(exit_status);
  116. thisfrq = basefrq;
  117. n = 1;
  118. while(thisfrq < dz->nyquist) {
  119. if((exit_status = get_channel_corresponding_to_frq(&truecc,thisfrq,dz))<0)
  120. return(exit_status);
  121. truevc = truecc * 2;
  122. if(dz->mode==OCT_DN_BASS && (thisfrq < basefrq))
  123. dz->flbufptr[0][truevc] =
  124. (float)(dz->param[OCT_BREI] - ((dz->param[OCT_BREI] - 1.0)*((double)n/(double)dz->iparam[OCT_HMOVE])));
  125. else {
  126. if((exit_status = getspecenvamp(&thisamp,thisfrq,0,dz))<0)
  127. return(exit_status);
  128. dz->flbufptr[0][truevc] = (float)thisamp;
  129. }
  130. truevc++;
  131. dz->flbufptr[0][truevc] = (float)thisfrq;
  132. do {
  133. n++;
  134. } while(n%dz->iparam[OCT_HMOVE]==0);
  135. thisfrq = basefrq * (double)n;
  136. }
  137. break;
  138. default:
  139. sprintf(errstr,"Unknown mode in specoct()\n");
  140. return(PROGRAM_ERROR);
  141. } /* NORMALISE */
  142. if((exit_status = get_totalamp(&post_totalamp,dz->flbufptr[0],dz->wanted))<0)
  143. return(exit_status);
  144. return normalise(pre_totalamp,post_totalamp,dz);
  145. }
  146. /****************************** SPECSHIFTP ****************************
  147. *
  148. * transpose (part of) spectrum.
  149. */
  150. int specshiftp(dataptr dz)
  151. {
  152. int exit_status;
  153. if(dz->vflag[SHP_IS_DEPTH] && flteq(dz->param[SHIFTP_DEPTH],0.0))
  154. return(FINISHED);
  155. if(dz->brksize[SHIFTP_FFRQ] || dz->brksize[SHIFTP_SHF1] || dz->brksize[SHIFTP_SHF2]) {
  156. convert_shiftp_vals(dz);
  157. if((exit_status = adjust_params_and_setup_internal_params_for_shiftp(dz))<0)
  158. return(exit_status);
  159. }
  160. if((exit_status = get_amp_and_frq(dz->flbufptr[0],dz))<0)
  161. return(exit_status);
  162. if(dz->vflag[SHP_IS_DEPTH]) {
  163. if((exit_status = reset_shiftps_according_to_depth_value(dz))<0)
  164. return(exit_status);
  165. }
  166. if((exit_status = do_spectral_shiftp(dz))<0)
  167. return(exit_status);
  168. if((exit_status = put_amp_and_frq(dz->flbufptr[0],dz))<0)
  169. return(exit_status);
  170. return(FINISHED);
  171. }
  172. /************************ DO_SPECTRAL_SHIFTP **********************/
  173. int do_spectral_shiftp(dataptr dz)
  174. {
  175. double shft = dz->param[SHIFTP_NS1];
  176. int j, k, kk;
  177. switch(dz->mode) {
  178. case(P_OCT_UP): /* MOVE SPECTRUM, above fdcno, UP AN OCTAVE */
  179. case(P_OCT_UP_AND_DN):
  180. k = dz->iparam[SHIFTP_FDCNO]*2;
  181. for(j = dz->clength-1; j>= k; j += -2) {
  182. dz->amp[j] = dz->amp[j/2];
  183. dz->freq[j] = (float)(2.0 * dz->freq[j/2]);
  184. dz->amp[j-1] = 0.0f;
  185. dz->freq[j-1] = 0.0f;
  186. }
  187. for(j = dz->iparam[SHIFTP_FDCNO]; j<k; j++) {
  188. dz->amp[j] = 0.0f;
  189. dz->freq[j] = 0.0f;
  190. }
  191. if(dz->mode==P_OCT_UP)
  192. break;
  193. case(P_OCT_DN): /* MOVE SPECTRUM, below fdcno, DOWN AN OCTAVE */
  194. kk = dz->iparam[SHIFTP_FDCNO]-1;
  195. j = round((double)kk/2.0);
  196. if( kk != (2*j))
  197. kk = kk-1;
  198. for(j = 0; j <= kk; j += 2) {
  199. k = j/2;
  200. dz->amp[k] = dz->amp[j];
  201. dz->freq[k] = (float)(dz->freq[j]/2.0);
  202. dz->amp[k+1] = 0.0f;
  203. dz->freq[k+1] = 0.0f;
  204. }
  205. kk = kk/2;
  206. kk = kk+2;
  207. for(j = kk; j<dz->iparam[SHIFTP_FDCNO]; j++) {
  208. dz->amp[j] = 0.0f;
  209. dz->freq[j] = 0.0f;
  210. }
  211. break;
  212. case(P_SHFT_UP): /* MOVE SPECTRUM, above fdcno, UP BY SHIFT */
  213. case(P_SHFT_UP_AND_DN):
  214. if( shft > 1.0) {
  215. j = dz->clength-1;
  216. k = round((double)j/shft);
  217. while( k >= dz->iparam[SHIFTP_FDCNO]) {
  218. dz->amp[j] = dz->amp[k];
  219. dz->freq[j] = (float)(shft * dz->freq[k]);
  220. j-- ;
  221. k = round((double)j/shft);
  222. }
  223. for( k=j; k>dz->iparam[SHIFTP_FDCNO];k-- ) {
  224. dz->amp[k] = 0.0f;
  225. dz->freq[k] = 0.0f;
  226. }
  227. } else {
  228. j = dz->iparam[SHIFTP_FDCNO];
  229. k = round((double)j/shft);
  230. while( k <= (dz->clength-1)) {
  231. dz->amp[j] = dz->amp[k];
  232. dz->freq[j] = (float)(shft * dz->freq[k]);
  233. j++ ;
  234. k = round((double)j/shft);
  235. }
  236. for( k=j; k<dz->clength; k++ ) {
  237. dz->amp[k] = 0.0f;
  238. dz->freq[k] = 0.0f;
  239. }
  240. }
  241. if(dz->mode==P_SHFT_UP)
  242. break;
  243. else
  244. shft = dz->param[SHIFTP_NS2];
  245. case(P_SHFT_DN): /* MOVE SPECTRUM, below fdcno, DOWN BY SHIFT */
  246. if( shft > 1.0) {
  247. j = dz->iparam[SHIFTP_FDCNO]-1;
  248. k = round((double)j/shft);
  249. while( k > 0) {
  250. dz->amp[j] = dz->amp[k];
  251. dz->freq[j] = (float)(shft * dz->freq[k]);
  252. j-- ;
  253. k = round((double)j/shft);
  254. }
  255. for( k=j; k>0 ;k-- ) {
  256. dz->amp[k] = 0.0f; /* AMP AND FREQ AT 0 Hz ARE RETAINED */
  257. dz->freq[k] = 0.0f;
  258. }
  259. } else {
  260. j = 1;
  261. k = round((double)j/shft);
  262. while( k <= dz->iparam[SHIFTP_FDCNO]-1) {
  263. dz->amp[j] = dz->amp[k];
  264. dz->freq[j] = (float)(shft * dz->freq[k]);
  265. j++ ;
  266. k = round((double)j/shft);
  267. }
  268. for( k=j; k<dz->iparam[SHIFTP_FDCNO]; k++ ) {
  269. dz->amp[k] = 0.0f;
  270. dz->freq[k] = 0.0f;
  271. }
  272. }
  273. break;
  274. default:
  275. sprintf(errstr,"unknown mode in do_spectral_shiftp()\n");
  276. return(PROGRAM_ERROR);
  277. }
  278. return(FINISHED);
  279. }
  280. /********************************** SPECTUNE ********************************/
  281. int spectune(dataptr dz)
  282. {
  283. int exit_status;
  284. chvptr loudest;
  285. int cc, vc;
  286. if(dz->vflag[TUNE_FBOT]) {
  287. for(cc = 0, vc = 0; vc < dz->wanted; cc++, vc += 2) {
  288. if(dz->flbufptr[0][FREQ] < dz->param[TUNE_BFRQ])
  289. dz->flbufptr[0][AMPP] = 0.0f;
  290. }
  291. }
  292. if(dz->vflag[TUNE_TRACE]) {
  293. if((exit_status = initialise_ring_vals(dz->iparam[TUNE_INDX],-1.0,dz))<0)
  294. return(exit_status);
  295. for(cc = 0, vc = 0; vc < dz->wanted; cc++, vc += 2) {
  296. if((exit_status = if_one_of_loudest_chans_store_in_ring(vc,dz))<0)
  297. return(exit_status);
  298. }
  299. memset((char *)(dz->iparray[TUNE_LOUD]),0,dz->clength * sizeof(int));
  300. loudest = dz->ringhead;
  301. do {
  302. dz->iparray[TUNE_LOUD][loudest->loc] = 1;
  303. } while((loudest = loudest->next)!=dz->ringhead);
  304. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  305. if(dz->iparray[TUNE_LOUD][cc]) {
  306. if((exit_status = replace_partial_by_tuned_partial(cc,vc,dz))<0)
  307. return(exit_status);
  308. } else
  309. dz->flbufptr[0][vc] = (float)(dz->flbufptr[0][vc] * dz->param[TUNE_CLAR]);
  310. }
  311. } else {
  312. for(cc = 0, vc = 0; vc < dz->wanted; cc++, vc += 2) {
  313. if(dz->frq_template[cc]>0.0) {
  314. if((exit_status = focus_partial_towards_tuned_value(FREQ,cc,dz))<0)
  315. return(exit_status);
  316. } else
  317. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[TUNE_CLAR]);
  318. }
  319. }
  320. return(FINISHED);
  321. }
  322. /************************** REPLACE_PARTIAL_BY_TUNED_PARTIAL *******************************/
  323. int replace_partial_by_tuned_partial(int cc,int vc,dataptr dz)
  324. {
  325. int exit_status;
  326. int aa = cc, bb = cc, here, there;
  327. double upratio, dnratio;
  328. if(dz->frq_template[cc]>0.0) /* if loudchan is a validfrq chan */
  329. return focus_partial_towards_tuned_value(FREQ,cc,dz);
  330. /* when loudchan NOT validfrq chan */
  331. while(aa>=0 && dz->frq_template[aa]<=0.0) /* search downwards */
  332. aa--;
  333. while(bb<dz->clength && dz->frq_template[bb]<=0.0) /* and upwards */
  334. bb++; /* for closest validfrq chans */
  335. if(aa<0 && bb<dz->clength) {
  336. here = bb*2; /* if none below, use one above */
  337. aa = bb;
  338. } else if(bb>=dz->clength && aa>=0) { /* if none above, use one below */
  339. here = aa*2;
  340. } else {
  341. here = aa*2; /* otherwise, choose nearest validfrq */
  342. there = bb*2;
  343. upratio = dz->flbufptr[0][there+1]/dz->flbufptr[0][FREQ];
  344. dnratio = dz->flbufptr[0][FREQ]/dz->flbufptr[0][here+1];
  345. if(upratio < dnratio) {
  346. here = there;
  347. aa = bb;
  348. }
  349. }
  350. if((exit_status = focus_partial_towards_tuned_value(here+1,aa,dz))<0)
  351. return(exit_status);
  352. dz->flbufptr[0][here] = dz->flbufptr[0][AMPP]; /* and gets ampl of nearest loudchan, */
  353. dz->flbufptr[0][AMPP] = 0.0F; /* while actual loudchan is zeroed out. */
  354. return(FINISHED);
  355. }
  356. /********************************* FOCUS_PARTIAL_TOWARDS_TUNED_VALUE *******************************/
  357. int focus_partial_towards_tuned_value(int vc, int cc,dataptr dz)
  358. {
  359. double frqshift;
  360. frqshift = dz->frq_template[cc] - dz->flbufptr[0][vc];
  361. frqshift *= dz->param[TUNE_FOC];
  362. dz->flbufptr[0][vc] = (float)(dz->flbufptr[0][vc] + frqshift);
  363. return(FINISHED);
  364. }
  365. /****************************** SPECPICK ****************************/
  366. int specpick(dataptr dz)
  367. {
  368. int exit_status;
  369. int mask = 1;
  370. int cc, vc, bflagno;
  371. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  372. if((exit_status = choose_bflagno_and_reset_mask_if_ness
  373. (&bflagno,cc,&mask,dz->iparam[PICK_LONGPOW2],dz->iparam[PICK_DIVMASK]))<0)
  374. return(exit_status);
  375. if(!(dz->lparray[PICK_BFLG][bflagno] & mask)) /* if bit NOT set, modify amplitude */
  376. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[PICK_CLAR]);
  377. mask <<= 1; /* move bitmask upwards */
  378. }
  379. return(FINISHED);
  380. }
  381. /***************************** SPECCHORD2 *********************************/
  382. int specchord2(dataptr dz)
  383. {
  384. int exit_status;
  385. int newvc, cc, vc, n;
  386. double pre_amptotal, post_amptotal;
  387. double thisamp, thisfrq;
  388. double hifrq = dz->param[CHORD_HIFRQ];
  389. double lofrq = dz->param[CHORD_LOFRQ];
  390. if(dz->brksize[CHORD_HIFRQ] || dz->brksize[CHORD_LOFRQ]) {
  391. if(hifrq < lofrq)
  392. swap(&hifrq,&lofrq);
  393. }
  394. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  395. return(exit_status);
  396. for(vc = 0; vc < dz->wanted; vc += 2)
  397. dz->windowbuf[0][AMPP] = 0.0F;
  398. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  399. for(n=0;n<dz->itemcnt;n++) { /* for each note of chord */
  400. if((exit_status = gotnewfrq2(&newvc,vc,&thisamp,&thisfrq,n,dz))<0)
  401. return(exit_status);
  402. if(exit_status==FALSE)
  403. continue;
  404. switch(dz->vflag[CHORD_BODY]) {
  405. case(CHD_LESSFUL):
  406. if((exit_status = move_data_into_appropriate_channel(vc,newvc,(float)thisamp,(float)thisfrq,dz))<0)
  407. return(exit_status);
  408. break;
  409. case(CHD_NORMAL):
  410. if((exit_status = move_data_into_some_appropriate_channel(newvc,(float)thisamp,(float)thisfrq,dz))<0)
  411. return(exit_status);
  412. break;
  413. default:
  414. sprintf(errstr,"Unknown case in dz->vflag[CHROD_BODY]: specchord()\n");
  415. return(PROGRAM_ERROR);
  416. }
  417. }
  418. }
  419. for(vc = 0; vc < dz->wanted; vc+=2)
  420. dz->flbufptr[0][AMPP] = dz->windowbuf[0][AMPP];
  421. if(dz->vflag[CHORD_FBOT] || dz->vflag[CHORD_FTOP]) {
  422. if((exit_status = remove_unwanted_frq_areas(lofrq,hifrq,dz))<0)
  423. return(exit_status);
  424. }
  425. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  426. return(exit_status);
  427. return normalise(pre_amptotal,post_amptotal,dz);
  428. }
  429. /*************************** GOTNEWFRQ2 *************************/
  430. int gotnewfrq2(int *newvc,int vc,double *thisamp,double *thisfrq,int n, dataptr dz)
  431. {
  432. int newcc;
  433. if((*thisfrq = fabs(dz->flbufptr[0][FREQ] * dz->transpos[n])) > dz->nyquist)
  434. return(FALSE);
  435. *thisamp = dz->flbufptr[0][AMPP];
  436. if((newcc = (int)((*thisfrq + dz->halfchwidth)/dz->chwidth)) >= dz->clength) /* TRUNCATE */
  437. return(FALSE);
  438. *newvc = newcc * 2;
  439. return(TRUE);
  440. }
  441. /************************* REMOVE_UNWANTED_FRQ_AREAS ***************************/
  442. int remove_unwanted_frq_areas(double lofrq_limit,double hifrq_limit,dataptr dz)
  443. {
  444. int cc, vc;
  445. if(dz->vflag[CHORD_FBOT]) {
  446. if(dz->vflag[CHORD_FTOP]) {
  447. for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
  448. if(dz->flbufptr[0][FREQ] < lofrq_limit || dz->flbufptr[0][FREQ] > hifrq_limit)
  449. dz->flbufptr[0][AMPP] = 0.0f;
  450. }
  451. } else {
  452. for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
  453. if(dz->flbufptr[0][FREQ] < lofrq_limit)
  454. dz->flbufptr[0][AMPP] = 0.0f;
  455. }
  456. }
  457. } else if(dz->vflag[CHORD_FTOP]) {
  458. for(cc = 0,vc = 0; cc < dz->clength; cc++, vc += 2) {
  459. if(dz->flbufptr[0][FREQ] > hifrq_limit)
  460. dz->flbufptr[0][AMPP] = 0.0f;
  461. }
  462. }
  463. return(FINISHED);
  464. }
  465. /***************************** SPECCHORD *********************************/
  466. int specchord(dataptr dz)
  467. {
  468. int exit_status;
  469. int newvc, cc, vc, n;
  470. double pre_amptotal, post_amptotal;
  471. double thisamp, thisfrq, thisspecamp;
  472. double hifrq = dz->param[CHORD_HIFRQ];
  473. double lofrq = dz->param[CHORD_LOFRQ];
  474. if(dz->brksize[CHORD_HIFRQ] || dz->brksize[CHORD_LOFRQ]) {
  475. if(hifrq < lofrq)
  476. swap(&hifrq,&lofrq);
  477. }
  478. if((exit_status = extract_specenv(0,0,dz))<0)
  479. return(exit_status);
  480. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  481. return(exit_status);
  482. for(vc = 0; vc < dz->wanted; vc += 2)
  483. dz->windowbuf[0][AMPP] = 0.0F;
  484. for( cc = 0 ,vc = 0; cc < dz->clength; cc++, vc += 2) {
  485. if((exit_status = getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
  486. return(exit_status);
  487. if(thisspecamp < VERY_TINY_VAL)
  488. continue;
  489. for(n=0;n<dz->itemcnt;n++) { /* for each note of chord */
  490. if((exit_status = gotnewfrq(&newvc,vc,&thisamp,&thisfrq,thisspecamp,n,dz))<0)
  491. return(exit_status);
  492. if(exit_status==FALSE)
  493. continue;
  494. switch(dz->vflag[CHORD_BODY]) {
  495. case(CHD_LESSFUL):
  496. if((exit_status = move_data_into_appropriate_channel(vc,newvc,(float)thisamp,(float)thisfrq,dz))<0)
  497. return(exit_status);
  498. break;
  499. case(CHD_NORMAL):
  500. if((exit_status = move_data_into_some_appropriate_channel(newvc,(float)thisamp,(float)thisfrq,dz))<0)
  501. return(exit_status);
  502. break;
  503. default:
  504. sprintf(errstr,"Unknown case in dz->vflag[CHROD_BODY]: specchord()\n");
  505. return(PROGRAM_ERROR);
  506. }
  507. }
  508. }
  509. for(vc = 0; vc < dz->wanted; vc+=2)
  510. dz->flbufptr[0][AMPP] = dz->windowbuf[0][AMPP];
  511. if(dz->vflag[CHORD_FBOT] || dz->vflag[CHORD_FTOP]) {
  512. if((exit_status = remove_unwanted_frq_areas(lofrq,hifrq,dz))<0)
  513. return(exit_status);
  514. }
  515. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  516. return(exit_status);
  517. return normalise(pre_amptotal,post_amptotal,dz);
  518. }
  519. /*************************** GOTNEWFRQ *************************/
  520. int gotnewfrq(int *newvc,int vc,double *thisamp,double *thisfrq, double thisspecamp,int n, dataptr dz)
  521. {
  522. int exit_status;
  523. int newcc;
  524. double newspecamp;
  525. if((*thisfrq = fabs(dz->flbufptr[0][FREQ] * dz->transpos[n])) > dz->nyquist)
  526. return(FALSE);
  527. if((exit_status = getspecenvamp(&newspecamp,(double)(*thisfrq),0,dz))<0)
  528. return(exit_status);
  529. if(newspecamp < VERY_TINY_VAL)
  530. return(FALSE);
  531. if((*thisamp = dz->flbufptr[0][AMPP]*newspecamp/thisspecamp)<VERY_TINY_VAL)
  532. return(FALSE);
  533. if((newcc = (int)((*thisfrq + dz->halfchwidth)/dz->chwidth)) >= dz->clength) /* TRUNCATE */
  534. return(FALSE);
  535. *newvc = newcc * 2;
  536. return(TRUE);
  537. }