ap_pvoc.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  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. /* May 2011 rebuilt with fixed mainfuncs.c for preserving sample type etc */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <structures.h>
  25. #include <cdpmain.h>
  26. #include <tkglobals.h>
  27. #include <pnames.h>
  28. #include <pvoc.h>
  29. #include <processno.h>
  30. #include <modeno.h>
  31. #include <globcon.h>
  32. #include <logic.h>
  33. #include <filetype.h>
  34. #include <mixxcon.h>
  35. #include <speccon.h>
  36. #include <flags.h>
  37. #include <arrays.h>
  38. #include <formants.h>
  39. #include <sfsys.h>
  40. #include <osbind.h>
  41. #include <string.h>
  42. #include <math.h>
  43. //RWD 2025 zero error checking - will already have been done!
  44. static int checkchans4format(int chans, const char* fname);
  45. /***************************************************************************************/
  46. /****************************** FORMERLY IN aplinit.c **********************************/
  47. /***************************************************************************************/
  48. /***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
  49. int establish_bufptrs_and_extra_buffers(dataptr dz)
  50. {
  51. dz->extra_bufcnt = -1; /* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
  52. dz->bptrcnt = 0;
  53. dz->bufcnt = 0;
  54. switch(dz->process) {
  55. case(PVOC_ANAL): dz->extra_bufcnt = 0; dz->bufcnt = 0; break;
  56. case(PVOC_SYNTH): dz->extra_bufcnt = 0; dz->bufcnt = 0; break;
  57. case(PVOC_EXTRACT): dz->extra_bufcnt = 0; dz->bufcnt = 0; break;
  58. default:
  59. sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
  60. return(PROGRAM_ERROR);
  61. }
  62. if(dz->extra_bufcnt < 0) {
  63. sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
  64. return(PROGRAM_ERROR);
  65. }
  66. return establish_groucho_bufptrs_and_extra_buffers(dz);
  67. }
  68. /***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
  69. int setup_internal_arrays_and_array_pointers(dataptr dz)
  70. {
  71. int n;
  72. dz->ptr_cnt = -1; /* base constructor...process */
  73. dz->array_cnt = -1;
  74. dz->iarray_cnt = -1;
  75. dz->larray_cnt = -1;
  76. switch(dz->process) {
  77. case(PVOC_ANAL): dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
  78. case(PVOC_SYNTH): dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
  79. case(PVOC_EXTRACT): dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt = 0; dz->ptr_cnt = 0; dz->fptr_cnt = 0; break;
  80. }
  81. /*** WARNING ***
  82. ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
  83. **** WARNING ***/
  84. if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
  85. sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");
  86. return(PROGRAM_ERROR);
  87. }
  88. if(dz->array_cnt > 0) {
  89. if((dz->parray = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
  90. sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
  91. return(MEMORY_ERROR);
  92. }
  93. for(n=0;n<dz->array_cnt;n++)
  94. dz->parray[n] = NULL;
  95. }
  96. if(dz->iarray_cnt > 0) {
  97. if((dz->iparray = (int **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
  98. sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
  99. return(MEMORY_ERROR);
  100. }
  101. for(n=0;n<dz->iarray_cnt;n++)
  102. dz->iparray[n] = NULL;
  103. }
  104. if(dz->larray_cnt > 0) {
  105. if((dz->lparray = (int **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
  106. sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
  107. return(MEMORY_ERROR);
  108. }
  109. for(n=0;n<dz->larray_cnt;n++)
  110. dz->lparray[n] = NULL;
  111. }
  112. if(dz->ptr_cnt > 0) {
  113. if((dz->ptr = (double **)malloc(dz->ptr_cnt * sizeof(double *)))==NULL) {
  114. sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
  115. return(MEMORY_ERROR);
  116. }
  117. for(n=0;n<dz->ptr_cnt;n++)
  118. dz->ptr[n] = NULL;
  119. }
  120. if(dz->fptr_cnt > 0) {
  121. if((dz->fptr = (float **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
  122. sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
  123. return(MEMORY_ERROR);
  124. }
  125. for(n=0;n<dz->fptr_cnt;n++)
  126. dz->fptr[n] = NULL;
  127. }
  128. return(FINISHED);
  129. }
  130. /****************************** ASSIGN_PROCESS_LOGIC *********************************/
  131. int assign_process_logic(dataptr dz)
  132. {
  133. switch(dz->process) {
  134. case(PVOC_ANAL): setup_process_logic(SNDFILES_ONLY, BIG_ANALFILE, ANALFILE_OUT, dz); break;
  135. case(PVOC_SYNTH): setup_process_logic(ANALFILE_ONLY, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
  136. case(PVOC_EXTRACT): setup_process_logic(SNDFILES_ONLY, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
  137. default:
  138. sprintf(errstr,"Unknown process: assign_process_logic()\n");
  139. return(PROGRAM_ERROR);
  140. break;
  141. }
  142. if(dz->has_otherfile) {
  143. switch(dz->input_data_type) {
  144. case(ALL_FILES):
  145. case(TWO_SNDFILES):
  146. case(SNDFILE_AND_ENVFILE):
  147. case(SNDFILE_AND_BRKFILE):
  148. case(SNDFILE_AND_UNRANGED_BRKFILE):
  149. case(SNDFILE_AND_DB_BRKFILE):
  150. break;
  151. case(MANY_SNDFILES):
  152. if(dz->process==INFO_TIMELIST)
  153. break;
  154. /* fall thro */
  155. default:
  156. sprintf(errstr,"Most processes accepting files with different properties\n"
  157. "can only take 2 sound infiles.\n");
  158. return(PROGRAM_ERROR);
  159. }
  160. }
  161. return(FINISHED);
  162. }
  163. /***************************** SET_LEGAL_INFILE_STRUCTURE **************************
  164. *
  165. * Allows 2nd infile to have different props to first infile.
  166. */
  167. void set_legal_infile_structure(dataptr dz)
  168. {
  169. switch(dz->process) {
  170. default:
  171. dz->has_otherfile = FALSE;
  172. break;
  173. }
  174. }
  175. /***************************************************************************************/
  176. /****************************** FORMERLY IN internal.c *********************************/
  177. /***************************************************************************************/
  178. /****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
  179. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  180. {
  181. int exit_status = FINISHED;
  182. switch(process) {
  183. case(PVOC_ANAL): exit_status = set_internalparam_data("000iiiiiiiiiiii",ap); break;
  184. case(PVOC_SYNTH): exit_status = set_internalparam_data("000iiiiiiiiiiii",ap); break;
  185. case(PVOC_EXTRACT): exit_status = set_internalparam_data( "iiiiiiiiiiii",ap); break;
  186. default:
  187. sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
  188. return(PROGRAM_ERROR);
  189. }
  190. return(exit_status);
  191. }
  192. /********************************************************************************************/
  193. /********************************** FORMERLY IN specialin.c *********************************/
  194. /********************************************************************************************/
  195. /********************** READ_SPECIAL_DATA ************************/
  196. int read_special_data(char *str,dataptr dz)
  197. {
  198. aplptr ap = dz->application;
  199. switch(ap->special_data) {
  200. default:
  201. sprintf(errstr,"Unknown special_data type: read_special_data()\n");
  202. return(PROGRAM_ERROR);
  203. }
  204. return(FINISHED); /* NOTREACHED */
  205. }
  206. /********************************************************************************************/
  207. /********************************** FORMERLY IN preprocess.c ********************************/
  208. /********************************************************************************************/
  209. /****************************** PARAM_PREPROCESS *********************************/
  210. int param_preprocess(dataptr dz)
  211. {
  212. switch(dz->process) {
  213. case(PVOC_ANAL):
  214. case(PVOC_SYNTH):
  215. case(PVOC_EXTRACT):
  216. return pvoc_preprocess(dz);
  217. default:
  218. sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
  219. return(PROGRAM_ERROR);
  220. }
  221. return(FINISHED); /* NOTREACHED */
  222. }
  223. /********************************************************************************************/
  224. /********************************** FORMERLY IN procgrou.c **********************************/
  225. /********************************************************************************************/
  226. /**************************** GROUCHO_PROCESS_FILE ****************************/
  227. int groucho_process_file(dataptr dz) /* FUNCTIONS FOUND IN PROCESS.C */
  228. {
  229. switch(dz->process) {
  230. case(PVOC_ANAL):
  231. case(PVOC_SYNTH):
  232. case(PVOC_EXTRACT): return pvoc_process(dz);
  233. default:
  234. sprintf(errstr,"Unknown case in process_file()\n");
  235. return(PROGRAM_ERROR);
  236. }
  237. return(FINISHED); /* NOTREACHED */
  238. }
  239. /********************************************************************************************/
  240. /********************************** FORMERLY IN buffers.c ***********************************/
  241. /********************************************************************************************/
  242. /**************************** ALLOCATE_LARGE_BUFFERS ******************************/
  243. int allocate_large_buffers(dataptr dz)
  244. {
  245. switch(dz->process) {
  246. case(PVOC_ANAL):
  247. case(PVOC_SYNTH):
  248. case(PVOC_EXTRACT):
  249. return FINISHED;
  250. default:
  251. sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
  252. return(PROGRAM_ERROR);
  253. }
  254. return(FINISHED); /* NOTREACHED */
  255. }
  256. /********************************************************************************************/
  257. /********************************** FORMERLY IN cmdline.c ***********************************/
  258. /********************************************************************************************/
  259. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  260. {
  261. if (!strcmp(prog_identifier_from_cmdline,"anal")) dz->process = PVOC_ANAL;
  262. else if(!strcmp(prog_identifier_from_cmdline,"synth")) dz->process = PVOC_SYNTH;
  263. else if(!strcmp(prog_identifier_from_cmdline,"extract")) dz->process = PVOC_EXTRACT;
  264. else {
  265. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  266. return(USAGE_ONLY);
  267. }
  268. return FINISHED;
  269. }
  270. /********************************************************************************************/
  271. /********************************** FORMERLY IN usage.c *************************************/
  272. /********************************************************************************************/
  273. /******************************** USAGE1 ********************************/
  274. int usage1(void)
  275. {
  276. sprintf(errstr,
  277. "USAGE: pvoc NAME (mode) infile outfile (parameters)\n"
  278. "\n"
  279. "where NAME can be any one of\n"
  280. "\n"
  281. "anal synth extract\n"
  282. "\n"
  283. "Type 'pvoc anal' for more info on pvoc anal option... ETC.\n");
  284. return(USAGE_ONLY);
  285. }
  286. /******************************** USAGE2 ********************************/
  287. int usage2(char *str)
  288. {
  289. if(!strcmp(str,"anal")) {
  290. sprintf(errstr,
  291. "CONVERT SOUNDFILE TO SPECTRAL FILE\n\n"
  292. "USAGE: pvoc anal mode infile outfile [-cpoints] [-ooverlap]\n\n"
  293. "MODES ARE....\n"
  294. "1) STANDARD ANALYSIS\n"
  295. "2) OUTPUT SPECTRAL ENVELOPE VALS ONLY\n"
  296. "3) OUTPUT SPECTRAL MAGNITUDE VALS ONLY\n"
  297. "POINTS No of analysis points (2-32768 (power of 2)): default 1024\n"
  298. " More points give better freq resolution\n"
  299. " but worse time-resolution (e.g. rapidly changing spectrum).\n"
  300. "OVERLAP Filter overlap factor (1-4): default 3\n");
  301. } else if(!strcmp(str,"synth")) {
  302. sprintf(errstr,
  303. "CONVERT SPECTRAL FILE TO SOUNDFILE\n\n"
  304. "USAGE: pvoc synth infile outfile\n");
  305. } else if(!strcmp(str,"extract")) {
  306. sprintf(errstr,
  307. "ANALYSE THEN RESYNTHESIZE SOUND WITH VARIOUS OPTIONS\n\n"
  308. "USAGE: pvoc extract infile outfile\n"
  309. " [-cpoints] [-ooverlap] [-ddochans] [-llochan] [-hhichan]\n\n"
  310. "POINTS No of analysis points (2-32768 (power of 2)): default 1024\n"
  311. " More points give better freq resolution\n"
  312. " but worse time-resolution (e.g. rapidly changing spectrum).\n"
  313. "OVERLAP Filter overlap factor (1-4): default 3\n"
  314. "DOCHANS resynthesize odd (1) or even (2) channels only.\n"
  315. "LOCHAN ignore analysis channels below this in resynth (default: 0)\n"
  316. "HICHAN ignore analysis channels above this in resynth (dflt: highest channel)\n"
  317. "LOCHAN and HICHAN refer to channels rather than analysis points.\n"
  318. " There is 1 channel for every 2 points.\n"
  319. " HICHAN should therefore not be > ANALYSIS POINTS/2\n"
  320. " To default to topmost chan, set at ZERO.\n\n"
  321. "NB If no flags are set, the output sound will be the same as the input.\n");
  322. } else
  323. sprintf(errstr,"Unknown option '%s'\n",str);
  324. return(USAGE_ONLY);
  325. }
  326. /******************************** USAGE3 ********************************/
  327. int usage3(char *str1,char *str2)
  328. {
  329. sprintf(errstr,"Insufficient parameters on command line.\n");
  330. return(USAGE_ONLY);
  331. }
  332. /********************************************************************************************/
  333. /********************************** FORMERLY IN pconsistency.c ******************************/
  334. /********************************************************************************************/
  335. /******************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY (redundant) *************************/
  336. int check_param_validity_and_consistency(dataptr dz)
  337. {
  338. int exit_status, chans;
  339. int chancnt, Nchans;
  340. int M, D, win_overlap;
  341. float arate;
  342. int srate;
  343. //RWD 2025
  344. const char* ofname = 0;
  345. switch(dz->process) {
  346. case(PVOC_ANAL):
  347. //RWD 2025 to trap excessive fft sizes for .ana
  348. ofname = dz->outfilename;
  349. chans = dz->infile->channels;
  350. srate = dz->infile->srate;
  351. win_overlap = dz->iparam[PVOC_WINOVLP_INPUT]-1;
  352. chancnt = dz->iparam[PVOC_CHANS_INPUT];
  353. chancnt = chancnt + (chancnt%2);
  354. //RWD 2025
  355. if(checkchans4format(chancnt,ofname) == 0) {
  356. sprintf(errstr,"Requested analysis channel count %d > 8192: too large for .ana format\n",chancnt);
  357. return DATA_ERROR;
  358. }
  359. switch(win_overlap) {
  360. case 0: M = 4*chancnt; break;
  361. case 1: M = 2*chancnt; break;
  362. case 2: M = chancnt; break;
  363. case 3: M = chancnt / 2; break;
  364. default:
  365. sprintf(errstr,"pvoc: Invalid window overlap factor.\n");
  366. return(PROGRAM_ERROR);
  367. }
  368. if((D = (int)(M/PVOC_CONSTANT_A)) == 0){
  369. fprintf(stdout,"WARNING: Decimation too low: adjusted.\n");
  370. fflush(stdout);
  371. D = 1;
  372. }
  373. Nchans = chancnt + 2;
  374. if(dz->mode == ENVEL_ONLY || dz->mode == MAG_ONLY) {
  375. Nchans /= 2;
  376. arate = (float)(Nchans * dz->infile->srate)/(float)D;
  377. } else
  378. arate = (float)dz->infile->srate/(float)D;
  379. dz->infile->srate = (int)arate;
  380. dz->infile->channels = chancnt + 2;
  381. if((exit_status = create_sized_outfile(dz->wordstor[0],dz))<0)
  382. return(exit_status);
  383. dz->infile->channels = chans;
  384. dz->infile->srate = srate;
  385. break;
  386. case(PVOC_SYNTH):
  387. chans = dz->infile->channels;
  388. srate = dz->infile->srate;
  389. dz->infile->channels = 1;
  390. dz->infile->srate = dz->infile->origrate;
  391. /*RWD OCT 05 set outfile stype to infile origstype */
  392. /* RWD Apr 2011 NB: will get changed if -f flag used */
  393. dz->outfile->stype = dz->infile->origstype;
  394. if((exit_status = create_sized_outfile(dz->wordstor[0],dz))<0)
  395. return(exit_status);
  396. dz->infile->channels = chans;
  397. dz->infile->srate = srate;
  398. break;
  399. }
  400. return (FINISHED);
  401. }
  402. /***************************** INNER_LOOP (redundant) **************************/
  403. int inner_loop
  404. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  405. {
  406. return(FINISHED);
  407. }
  408. //RWD 2025 zero error checking - will already have been done!
  409. static int checkchans4format(int chans, const char* fname)
  410. {
  411. char *lastdot;
  412. lastdot = strrchr(fname,'.');
  413. if(chans > 8192){
  414. if((_stricmp(lastdot,".wav")==0)
  415. || (_stricmp(lastdot,".ana")==0))
  416. return 0;
  417. }
  418. return 1;
  419. }