fltprepro.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  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. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <memory.h>
  24. #include <structures.h>
  25. #include <tkglobals.h>
  26. #include <processno.h>
  27. #include <modeno.h>
  28. #include <arrays.h>
  29. #include <globcon.h>
  30. #include <filters.h>
  31. #include <math.h>
  32. #include <osbind.h>
  33. static int setup_lphp_filter(dataptr dz);
  34. static int calc_frqs(dataptr dz);
  35. static void randomise_frqs(dataptr dz);
  36. static int allocate_internal_params_lphp(int chans,dataptr dz);
  37. static void calculate_filter_poles_lphp(double signd,int filter_order,dataptr dz);
  38. static void initialise_filter_coeffs_lphp(int chans,dataptr dz);
  39. static int allocate_filter_internalparam_arrays(int fltcnt,dataptr dz);
  40. static int initialise_filter_params(dataptr dz);
  41. static int establish_order_of_filter(dataptr dz);
  42. static int initialise_fltbankv2(dataptr dz);
  43. /************************** FILTER_PREPROCESS **************************/
  44. int filter_preprocess(dataptr dz)
  45. {
  46. int exit_status;
  47. int n;
  48. if(dz->process == FLTBANKV2) {
  49. if((exit_status = initialise_fltbankv2(dz))<0)
  50. return exit_status;
  51. }
  52. switch(dz->process) {
  53. case(EQ):
  54. case(FSTATVAR):
  55. case(FLTSWEEP):
  56. case(ALLPASS):
  57. break;
  58. case(LPHP):
  59. if((exit_status = setup_lphp_filter(dz))<0)
  60. return(exit_status);
  61. break;
  62. case(FLTBANKC):
  63. return calc_frqs(dz);
  64. case(FLTBANKN):
  65. if((exit_status = calc_frqs(dz))<0)
  66. return(exit_status);
  67. for(n=0;n<dz->iparam[FLT_CNT];n++)
  68. dz->parray[FLT_AMP][n] = 1.0;
  69. /* fall thro */
  70. case(FLTBANKU):
  71. case(FLTBANKV2):
  72. case(FLTBANKV):
  73. case(FLTITER):
  74. if((exit_status = allocate_filter_internalparam_arrays(dz->iparam[FLT_CNT],dz))<0)
  75. return(exit_status);
  76. if((exit_status = initialise_filter_params(dz))<0)
  77. return(exit_status);
  78. break;
  79. default:
  80. sprintf(errstr,"Unknown case in filter_preprocess()\n");
  81. return(PROGRAM_ERROR);
  82. }
  83. return(FINISHED);
  84. }
  85. /********************************* SETUP_LPHP_FILTER *****************************/
  86. int setup_lphp_filter(dataptr dz)
  87. {
  88. int exit_status;
  89. int filter_order;
  90. double signd = 1.0;
  91. if (dz->param[FLT_PASSFRQ] < dz->param[FLT_STOPFRQ]) /* low pass */
  92. signd = -1.0;
  93. filter_order = establish_order_of_filter(dz);
  94. if((exit_status = allocate_internal_params_lphp(dz->infile->channels,dz))<0)
  95. return(exit_status);
  96. calculate_filter_poles_lphp(signd,filter_order,dz);
  97. initialise_filter_coeffs_lphp(dz->infile->channels,dz);
  98. return(FINISHED);
  99. }
  100. /***************************** CALC_FRQS **********************************/
  101. int calc_frqs(dataptr dz)
  102. {
  103. double interval, one_over_total_steps;
  104. int n;
  105. switch(dz->mode) {
  106. case(FLT_EQUALSPAN):
  107. one_over_total_steps = 1.0/(double)dz->iparam[FLT_CNT];
  108. for(n=0;n<dz->iparam[FLT_CNT];n++) {
  109. interval = dz->param[FLT_HIFRQ]/dz->param[FLT_LOFRQ];
  110. dz->parray[FLT_FRQ][n] = dz->param[FLT_LOFRQ] * pow(interval,(double)n * one_over_total_steps);
  111. }
  112. break;
  113. case(FLT_EQUALINT):
  114. dz->parray[FLT_FRQ][0] = dz->param[FLT_LOFRQ];
  115. for(n=1;n<dz->iparam[FLT_CNT];n++)
  116. dz->parray[FLT_FRQ][n] = dz->parray[FLT_FRQ][n-1] * dz->param[FLT_INTSIZE];
  117. break;
  118. case(FLT_HARMONIC): /* offset = 0.0 */
  119. case(FLT_LINOFFSET):
  120. dz->parray[FLT_FRQ][0] = dz->param[FLT_LOFRQ];
  121. for(n=1;n<dz->iparam[FLT_CNT];n++)
  122. dz->parray[FLT_FRQ][n] = (dz->param[FLT_LOFRQ] * (double)(n+1))+dz->param[FLT_OFFSET];
  123. break;
  124. case(FLT_ALTERNATE):
  125. dz->parray[FLT_FRQ][0] = dz->param[FLT_LOFRQ];
  126. for(n=1;n<dz->iparam[FLT_CNT];n++)
  127. dz->parray[FLT_FRQ][n] = dz->param[FLT_LOFRQ] * (double)((n*2)+1);
  128. break;
  129. case(FLT_SUBHARM): /* dz->param[FLT_LOFRQ] already reset at top */
  130. dz->parray[FLT_FRQ][0] = dz->param[FLT_HIFRQ];
  131. for(n=1;n<dz->iparam[FLT_CNT];n++)
  132. dz->parray[FLT_FRQ][n] = dz->param[FLT_HIFRQ]/(double)(n+1);
  133. break;
  134. default:
  135. sprintf(errstr,"Unknown mode in calc_frqs()\n");
  136. return(PROGRAM_ERROR);
  137. }
  138. if(!flteq(dz->param[FLT_RANDFACT],0.0))
  139. randomise_frqs(dz);
  140. return(FINISHED);
  141. }
  142. /************************ RANDOMISE_FRQS *******************************/
  143. void randomise_frqs(dataptr dz)
  144. {
  145. int n;
  146. double thisrand, frqratio, interval;
  147. for(n=1;n<dz->iparam[FLT_CNT]-1;n++) {
  148. thisrand = drand48(); /* RANGE 0 - 1 */
  149. if(thisrand >= 0.5) { /* IF IN TOP 1/2 */
  150. thisrand -= 0.5; /* REDUCE BY 1/2 */
  151. thisrand *= dz->param[FLT_RANDFACT]; /* SCALE BY randfact */
  152. frqratio = dz->parray[FLT_FRQ][n+1]/dz->parray[FLT_FRQ][n];
  153. interval = log(frqratio) * thisrand;
  154. frqratio = exp(interval);
  155. dz->parray[FLT_FRQ][n] *= frqratio;
  156. /* SCATTER FRQ IN 1/2 INTERVAL ABOVE CURRENT VAL */
  157. } else {
  158. thisrand *= dz->param[FLT_RANDFACT]; /* SCALE BY randfact */
  159. frqratio = dz->parray[FLT_FRQ][n]/dz->parray[FLT_FRQ][n-1];
  160. interval = log(frqratio) * (1.0 - thisrand);
  161. frqratio = exp(interval);
  162. dz->parray[FLT_FRQ][n] = dz->parray[FLT_FRQ][n-1] * frqratio;
  163. /* SCATTER FRQ IN 1/2 INTERVAL BELOW CURRENT VAL */
  164. }
  165. }
  166. }
  167. /********************************* ALLOCATE_INTERNAL_PARAMS_LPHP *****************************/
  168. //int allocate_internal_params_lphp(int chans,dataptr dz)
  169. //{
  170. // if((dz->parray[FLT_DEN1] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  171. // || (dz->parray[FLT_DEN2] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  172. // || (dz->parray[FLT_CN] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  173. // || (dz->parray[FLT_S1] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  174. // || (dz->parray[FLT_E1] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  175. // || (dz->parray[FLT_S2] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  176. // || (dz->parray[FLT_E2] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL) {
  177. // sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
  178. // return(MEMORY_ERROR);
  179. // }
  180. // if(chans==2) {
  181. // if((dz->parray[FLT_S1S] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  182. // || (dz->parray[FLT_E1S] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  183. // || (dz->parray[FLT_S2S] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL
  184. // || (dz->parray[FLT_E2S] = (double *)malloc(dz->iparam[FLT_CNT] * sizeof(double)))==NULL) {
  185. // sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter stereo parameters.\n");
  186. // return(MEMORY_ERROR);
  187. // }
  188. // }
  189. // return(FINISHED);
  190. //}
  191. //
  192. // TW MULTICHAN 2010
  193. int allocate_internal_params_lphp(int chans,dataptr dz)
  194. {
  195. int i;
  196. if((dz->parray[FLT_DEN1] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  197. || (dz->parray[FLT_DEN2] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  198. || (dz->parray[FLT_CN] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  199. || (dz->parray[FLT_S1_BASE] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  200. || (dz->parray[FLT_E1_BASE] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  201. || (dz->parray[FLT_S2_BASE] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  202. || (dz->parray[FLT_E2_BASE] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL) {
  203. sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
  204. return(MEMORY_ERROR);
  205. }
  206. for(i = 1; i < chans;i++) {
  207. int index = i*FLT_LPHP_ARRAYS_PER_FILTER;
  208. if((dz->parray[FLT_S1_BASE + index] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  209. || (dz->parray[FLT_E1_BASE + index] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  210. || (dz->parray[FLT_S2_BASE + index] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL
  211. || (dz->parray[FLT_E2_BASE + index] = (double *)calloc(dz->iparam[FLT_CNT] * sizeof(double),sizeof(char)))==NULL) {
  212. sprintf(errstr,"INSUFFICIENT MEMORY for arrays of %d-channel filter parameters.\n",chans);
  213. return(MEMORY_ERROR);
  214. }
  215. }
  216. return(FINISHED);
  217. }
  218. /********************************* CALCULATE_FILTER_POLES_LPHP *****************************/
  219. void calculate_filter_poles_lphp(double signd,int filter_order,dataptr dz)
  220. {
  221. double ss, xx, aa, tppwr, x1, x2, cc;
  222. double pii = 4.0 * atan(1.0);
  223. double tp = tan(dz->param[FLT_PASSFRQ]);
  224. int k;
  225. ss = pii / (double)(2 * filter_order);
  226. for (k = 0; k < dz->iparam[FLT_CNT]; k++ ) {
  227. //TW : RWD CORRECTION TALLIES WITH MY UPDATES
  228. xx = (double) ((2.0 * (k+1)) - 1.0);
  229. aa = -sin(xx * ss);
  230. tppwr = pow(tp,2.0);
  231. cc = 1.0 - (2.0 * aa * tp) + tppwr;
  232. x1 = 2.0 * (tppwr - 1.0)/cc ;
  233. x2 = (1.0 + (2.0 * aa * tp) + tppwr)/cc ;
  234. dz->parray[FLT_DEN1][k] = signd * x1;
  235. dz->parray[FLT_DEN2][k] = -x2 ;
  236. dz->parray[FLT_CN][k] = pow(tp,2.0)/cc ;
  237. }
  238. }
  239. /********************************* INITIALISE_FILTER_COEFFS_LPHP *****************************/
  240. //void initialise_filter_coeffs_lphp(int chans,dataptr dz)
  241. //{
  242. // int k;
  243. // for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
  244. // dz->parray[FLT_S1][k] = 0.0;
  245. // dz->parray[FLT_S2][k] = 0.0;
  246. // dz->parray[FLT_E1][k] = 0.0;
  247. // dz->parray[FLT_E2][k] = 0.0;
  248. // }
  249. // if(chans==STEREO) {
  250. // for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
  251. // dz->parray[FLT_S1S][k] = 0.0;
  252. // dz->parray[FLT_S2S][k] = 0.0;
  253. // dz->parray[FLT_E1S][k] = 0.0;
  254. // dz->parray[FLT_E2S][k] = 0.0;
  255. // }
  256. // }
  257. //}
  258. //
  259. // TW MULTICHAN 2010
  260. void initialise_filter_coeffs_lphp(int chans,dataptr dz)
  261. {
  262. int k;
  263. int i,index;
  264. for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
  265. dz->parray[FLT_S1_BASE][k] = 0.0;
  266. dz->parray[FLT_S2_BASE][k] = 0.0;
  267. dz->parray[FLT_E1_BASE][k] = 0.0;
  268. dz->parray[FLT_E2_BASE][k] = 0.0;
  269. }
  270. for(i=1;i < chans; i++){
  271. index = i * FLT_LPHP_ARRAYS_PER_FILTER;
  272. for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
  273. dz->parray[FLT_S1_BASE + index][k] = 0.0;
  274. dz->parray[FLT_S2_BASE + index][k] = 0.0;
  275. dz->parray[FLT_E1_BASE + index][k] = 0.0;
  276. dz->parray[FLT_E2_BASE + index][k] = 0.0;
  277. }
  278. }
  279. }
  280. /**************************** ALLOCATE_FILTER_INTERNALPARAM_ARRAYS *******************************/
  281. int allocate_filter_internalparam_arrays(int fltcnt,dataptr dz)
  282. {
  283. int chans = dz->infile->channels;
  284. if((dz->parray[FLT_AMPL] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
  285. || (dz->parray[FLT_A] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
  286. || (dz->parray[FLT_B] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
  287. || (dz->parray[FLT_WW] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
  288. || (dz->parray[FLT_COSW] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
  289. || (dz->parray[FLT_SINW] = (double *)calloc(fltcnt * sizeof(double),sizeof(char)))==NULL
  290. || (dz->parray[FLT_Y] = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL
  291. || (dz->parray[FLT_Z] = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL) {
  292. sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
  293. return(MEMORY_ERROR);
  294. }
  295. if(dz->vflag[FLT_DBLFILT]) {
  296. if((dz->parray[FLT_D] = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL
  297. || (dz->parray[FLT_E] = (double *)calloc(fltcnt * chans * sizeof(double),sizeof(char)))==NULL) {
  298. sprintf(errstr,"INSUFFICIENT MEMORY for double filtering parameters.\n");
  299. return(MEMORY_ERROR);
  300. }
  301. }
  302. return(FINISHED);
  303. }
  304. /************************ INITIALISE_FILTER_PARAMS ***************************/
  305. int initialise_filter_params(dataptr dz)
  306. {
  307. int n, chno, k;
  308. int chans = dz->infile->channels;
  309. for(n=0;n<dz->iparam[FLT_CNT];n++) {
  310. get_coeffs1(n,dz);
  311. get_coeffs2(n,dz);
  312. for(chno=0;chno<chans;chno++) {
  313. k = (n*chans)+chno;
  314. if(dz->vflag[FLT_DBLFILT]) {
  315. dz->parray[FLT_D][k] = 0.0;
  316. dz->parray[FLT_E][k] = 0.0;
  317. }
  318. dz->parray[FLT_Y][k] = 0.0;
  319. dz->parray[FLT_Z][k] = 0.0;
  320. }
  321. }
  322. return(FINISHED);
  323. }
  324. /********************************* ESTABLISH_ORDER_OF_FILTER *****************************/
  325. int establish_order_of_filter(dataptr dz)
  326. {
  327. int filter_order;
  328. double tc, tp, tt, pii, xx, yy;
  329. double sr = (double)dz->infile->srate;
  330. if (dz->param[FLT_PASSFRQ] < dz->param[FLT_STOPFRQ]) /* low pass */
  331. dz->param[FLT_MUL] = 2.0;
  332. else {
  333. dz->param[FLT_MUL] = -2.0;
  334. dz->param[FLT_PASSFRQ] = dz->nyquist - dz->param[FLT_PASSFRQ];
  335. dz->param[FLT_STOPFRQ] = dz->nyquist - dz->param[FLT_STOPFRQ];
  336. }
  337. pii = 4.0 * atan(1.0);
  338. dz->param[FLT_PASSFRQ] = pii * dz->param[FLT_PASSFRQ]/sr;
  339. tp = tan(dz->param[FLT_PASSFRQ]);
  340. dz->param[FLT_STOPFRQ] = pii * dz->param[FLT_STOPFRQ]/sr;
  341. tc = tan(dz->param[FLT_STOPFRQ]);
  342. tt = tc / tp ;
  343. tt = (tt * tt);
  344. dz->param[FLT_GAIN] = fabs(dz->param[FLT_GAIN]);
  345. dz->param[FLT_GAIN] = dz->param[FLT_GAIN] * log(10.0)/10.0 ;
  346. dz->param[FLT_GAIN] = exp(dz->param[FLT_GAIN]) - 1.0 ;
  347. xx = log(dz->param[FLT_GAIN])/log(tt) ;
  348. yy = floor(xx);
  349. if ((xx - yy) == 0.0 )
  350. yy = yy - 1.0 ;
  351. filter_order = ((int)yy) + 1;
  352. if (filter_order <= 1)
  353. filter_order = 2;
  354. dz->iparam[FLT_CNT] = filter_order/2 ;
  355. filter_order = 2 * dz->iparam[FLT_CNT] ;
  356. fprintf(stdout,"INFO: Order of filter is %d\n", filter_order);
  357. fflush(stdout);
  358. dz->iparam[FLT_CNT] = min(dz->iparam[FLT_CNT],FLT_LBF);
  359. filter_order = 2 * dz->iparam[FLT_CNT];
  360. return(filter_order);
  361. }
  362. /**************************** INITIALISE_FLTBANKV2 *******************************/
  363. int initialise_fltbankv2(dataptr dz)
  364. {
  365. int n, k/*, z*/;
  366. memset((char *)dz->parray[FLT_INFRQ],0,dz->iparam[FLT_CNT] * sizeof(double));
  367. memset((char *)dz->parray[FLT_INAMP],0,dz->iparam[FLT_CNT] * sizeof(double));
  368. for(n = 1,k = 0; n < dz->iparam[FLT_ENTRYCNT];n+=2,k += dz->iparam[FLT_HARMCNT]) {
  369. dz->parray[FLT_INFRQ][k] = dz->parray[FLT_FBRK][n]; /* Get frqs of fundamentals into array, leaving space for harmonics */
  370. dz->parray[FLT_INAMP][k] = dz->parray[FLT_FBRK][n+1]; /* Get amps of fundamentals into array, leaving space for harmonics */
  371. }
  372. for(n = 1,k=0; n < dz->iparam[HRM_ENTRYCNT];n+=2,k++) {
  373. dz->parray[HARM_FRQ_CALC][k] = dz->parray[FLT_HBRK][n];
  374. dz->parray[HARM_AMP_CALC][k] = dz->parray[FLT_HBRK][n+1];
  375. }
  376. for(n=0;n<dz->iparam[FLT_CNT];n+=dz->iparam[FLT_HARMCNT]) {
  377. // z = 0;
  378. for(k=0; k < dz->iparam[FLT_HARMCNT];k++) { /* calc vals for partials from basefrq vals */
  379. dz->parray[FLT_INFRQ][n+k] = dz->parray[FLT_INFRQ][n] * dz->parray[HARM_FRQ_CALC][k];
  380. dz->parray[FLT_INAMP][n+k] = dz->parray[FLT_INAMP][n] * dz->parray[HARM_AMP_CALC][k];
  381. }
  382. }
  383. return(FINISHED);
  384. }