ap_synthesis.c 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260
  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. /* RWD/TW 24/02/18: removed usage ref to "Outputs..." names */
  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 <synth.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. #include <srates.h>
  44. //TW UPDATES
  45. #include <ctype.h>
  46. #include <special.h>
  47. #ifndef HUGE
  48. #define HUGE 3.40282347e+38F
  49. #endif
  50. /********************************************************************************************/
  51. /********************************** FORMERLY IN pconsistency.c ******************************/
  52. /********************************************************************************************/
  53. static int synth_consistency(dataptr dz);
  54. static void init_specsynth(dataptr dz);
  55. static int specsynth_consistency(dataptr dz);
  56. //TW UPDATE: new functions
  57. static int read_clicktrack_data(char *,dataptr dz);
  58. static int gettempo(char *str,double *tempo,double *pulse_unit,double *accel,int linecnt,int *GP,int *is_abstime);
  59. static int getmeter(char *str,int *metre_num,int *metre_denom,int linecnt,int GP,int is_abstime,double *abstime,int *accent);
  60. static int getstyle(char *str,char *style,int metre_num,int linecnt,int GP,int is_abstime);
  61. static int getcount(char *str,int *barcnt,int linecnt,int GP,int is_abstime,double *timeincr);
  62. static int generate_clickdata(int init,int *arraysize,double tempo,double pulse_unit,int metre_num,int metre_denom,
  63. char *style,int barcnt,double accel,double *time,double *lasttime,
  64. int GP,int is_abstime,double abstime,int accent,double timeincr,int *tcnt,int *tarray,
  65. double *mintimestep,dataptr dz);
  66. static int default_style(char *style,int metre_num);
  67. static int generate_clicktable(dataptr dz);
  68. static int click_consistency(dataptr dz);
  69. static int getlineno(char *str,int tcnt,int linecnt);
  70. static int read_chord_data(char *str,dataptr dz);
  71. /***************************************************************************************/
  72. /****************************** FORMERLY IN aplinit.c **********************************/
  73. /***************************************************************************************/
  74. /***************************** ESTABLISH_BUFPTRS_AND_EXTRA_BUFFERS **************************/
  75. int establish_bufptrs_and_extra_buffers(dataptr dz)
  76. {
  77. int exit_status;
  78. int is_spec = FALSE;
  79. dz->extra_bufcnt = -1; /* ENSURE EVERY CASE HAS A PAIR OF ENTRIES !! */
  80. dz->bptrcnt = 0;
  81. dz->bufcnt = 0;
  82. switch(dz->process) {
  83. case(SYNTH_SPEC):
  84. is_spec = TRUE;
  85. dz->extra_bufcnt = 0; dz->bptrcnt = 5;
  86. break;
  87. case(SYNTH_WAVE):
  88. case(MULTI_SYN):
  89. case(SYNTH_NOISE):
  90. case(SYNTH_SIL):
  91. //TW UPDATE
  92. case(CLICK):
  93. dz->extra_bufcnt = 0; dz->bufcnt = 1;
  94. break;
  95. default:
  96. sprintf(errstr,"Unknown program type [%d] in establish_bufptrs_and_extra_buffers()\n",dz->process);
  97. return(PROGRAM_ERROR);
  98. }
  99. if(dz->extra_bufcnt < 0) {
  100. sprintf(errstr,"bufcnts have not been set: establish_bufptrs_and_extra_buffers()\n");
  101. return(PROGRAM_ERROR);
  102. }
  103. if(is_spec)
  104. return establish_spec_bufptrs_and_extra_buffers(dz);
  105. else if((dz->process==HOUSE_SPEC && dz->mode==HOUSE_CONVERT) || dz->process==INFO_DIFF) {
  106. if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0)
  107. return(exit_status);
  108. }
  109. return establish_groucho_bufptrs_and_extra_buffers(dz);
  110. }
  111. /***************************** SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS **************************/
  112. int setup_internal_arrays_and_array_pointers(dataptr dz)
  113. {
  114. int n;
  115. dz->ptr_cnt = -1; /* base constructor...process */
  116. dz->array_cnt = -1;
  117. dz->iarray_cnt = -1;
  118. dz->larray_cnt = -1;
  119. switch(dz->process) {
  120. //TW UPDATE
  121. case(CLICK): dz->array_cnt=3; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
  122. case(SYNTH_WAVE):
  123. case(SYNTH_NOISE): dz->array_cnt=1; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
  124. case(MULTI_SYN): dz->array_cnt=4; dz->iarray_cnt=0; dz->larray_cnt=1; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
  125. case(SYNTH_SPEC):
  126. case(SYNTH_SIL): dz->array_cnt=0; dz->iarray_cnt=0; dz->larray_cnt=0; dz->ptr_cnt= 0; dz->fptr_cnt = 0; break;
  127. }
  128. /*** WARNING ***
  129. ANY APPLICATION DEALING WITH A NUMLIST INPUT: MUST establish AT LEAST 1 double array: i.e. dz->array_cnt = at least 1
  130. **** WARNING ***/
  131. if(dz->array_cnt < 0 || dz->iarray_cnt < 0 || dz->larray_cnt < 0 || dz->ptr_cnt < 0 || dz->fptr_cnt < 0) {
  132. sprintf(errstr,"array_cnt not set in setup_internal_arrays_and_array_pointers()\n");
  133. return(PROGRAM_ERROR);
  134. }
  135. if(dz->array_cnt > 0) {
  136. if((dz->parray = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
  137. sprintf(errstr,"INSUFFICIENT MEMORY for internal double arrays.\n");
  138. return(MEMORY_ERROR);
  139. }
  140. for(n=0;n<dz->array_cnt;n++)
  141. dz->parray[n] = NULL;
  142. }
  143. if(dz->iarray_cnt > 0) {
  144. if((dz->iparray = (int **)malloc(dz->iarray_cnt * sizeof(int *)))==NULL) {
  145. sprintf(errstr,"INSUFFICIENT MEMORY for internal int arrays.\n");
  146. return(MEMORY_ERROR);
  147. }
  148. for(n=0;n<dz->iarray_cnt;n++)
  149. dz->iparray[n] = NULL;
  150. }
  151. if(dz->larray_cnt > 0) {
  152. if((dz->lparray = (int **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
  153. sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
  154. return(MEMORY_ERROR);
  155. }
  156. for(n=0;n<dz->larray_cnt;n++)
  157. dz->lparray[n] = NULL;
  158. }
  159. if(dz->ptr_cnt > 0) {
  160. if((dz->ptr = (double **)malloc(dz->ptr_cnt * sizeof(double *)))==NULL) {
  161. sprintf(errstr,"INSUFFICIENT MEMORY for internal pointer arrays.\n");
  162. return(MEMORY_ERROR);
  163. }
  164. for(n=0;n<dz->ptr_cnt;n++)
  165. dz->ptr[n] = NULL;
  166. }
  167. if(dz->fptr_cnt > 0) {
  168. if((dz->fptr = (float **)malloc(dz->fptr_cnt * sizeof(float *)))==NULL) {
  169. sprintf(errstr,"INSUFFICIENT MEMORY for internal float-pointer arrays.\n");
  170. return(MEMORY_ERROR);
  171. }
  172. for(n=0;n<dz->fptr_cnt;n++)
  173. dz->fptr[n] = NULL;
  174. }
  175. return(FINISHED);
  176. }
  177. /****************************** ASSIGN_PROCESS_LOGIC *********************************/
  178. int assign_process_logic(dataptr dz)
  179. {
  180. switch(dz->process) {
  181. //TW UPDATE
  182. case(CLICK): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
  183. case(MULTI_SYN):
  184. case(SYNTH_WAVE): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
  185. case(SYNTH_NOISE): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
  186. case(SYNTH_SIL): setup_process_logic(NO_FILE_AT_ALL, UNEQUAL_SNDFILE, SNDFILE_OUT, dz); break;
  187. case(SYNTH_SPEC): setup_process_logic(NO_FILE_AT_ALL, BIG_ANALFILE, NO_OUTPUTFILE, dz); break;
  188. default:
  189. sprintf(errstr,"Unknown process: assign_process_logic()\n");
  190. return(PROGRAM_ERROR);
  191. break;
  192. }
  193. if(dz->has_otherfile) {
  194. switch(dz->input_data_type) {
  195. case(ALL_FILES):
  196. case(TWO_SNDFILES):
  197. case(SNDFILE_AND_ENVFILE):
  198. case(SNDFILE_AND_BRKFILE):
  199. case(SNDFILE_AND_UNRANGED_BRKFILE):
  200. case(SNDFILE_AND_DB_BRKFILE):
  201. break;
  202. case(MANY_SNDFILES):
  203. if(dz->process==INFO_TIMELIST)
  204. break;
  205. /* fall thro */
  206. default:
  207. sprintf(errstr,"Most processes accepting files with different properties\n"
  208. "can only take 2 sound infiles.\n");
  209. return(PROGRAM_ERROR);
  210. }
  211. }
  212. return(FINISHED);
  213. }
  214. /***************************** SET_LEGAL_INFILE_STRUCTURE **************************
  215. *
  216. * Allows 2nd infile to have different props to first infile.
  217. */
  218. void set_legal_infile_structure(dataptr dz)
  219. {
  220. switch(dz->process) {
  221. default:
  222. dz->has_otherfile = FALSE;
  223. break;
  224. }
  225. }
  226. /****************************** FORMERLY IN internal.c *********************************/
  227. /***************************************************************************************/
  228. /****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
  229. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  230. {
  231. int exit_status = FINISHED;
  232. switch(process) {
  233. //TW UPDATE
  234. case(CLICK): exit_status = set_internalparam_data("i",ap); break;
  235. case(SYNTH_SPEC):
  236. case(MULTI_SYN):
  237. case(SYNTH_WAVE): exit_status = set_internalparam_data("",ap); break;
  238. case(SYNTH_NOISE): exit_status = set_internalparam_data("0",ap); break;
  239. case(SYNTH_SIL): exit_status = set_internalparam_data("00",ap); break;
  240. default:
  241. sprintf(errstr,"Unknown process in set_legal_internalparam_structure()\n");
  242. return(PROGRAM_ERROR);
  243. }
  244. return(exit_status);
  245. }
  246. /********************************************************************************************/
  247. /********************************** FORMERLY IN specialin.c *********************************/
  248. /********************************************************************************************/
  249. /********************** READ_SPECIAL_DATA ************************/
  250. int read_special_data(char *str,dataptr dz)
  251. {
  252. aplptr ap = dz->application;
  253. switch(ap->special_data) {
  254. //TW UPDATE
  255. case(CLICKTRACK):
  256. dz->infile->srate = CLICK_SRATE;
  257. return read_clicktrack_data(str,dz);
  258. case(CHORD_SYN):
  259. dz->infile->srate = CLICK_SRATE;
  260. return read_chord_data(str,dz);
  261. default:
  262. sprintf(errstr,"Unknown special_data type: read_special_data()\n");
  263. return(PROGRAM_ERROR);
  264. }
  265. return(FINISHED); /* NOTREACHED */
  266. }
  267. /********************************************************************************************/
  268. /********************************** FORMERLY IN preprocess.c ********************************/
  269. /********************************************************************************************/
  270. /****************************** PARAM_PREPROCESS *********************************/
  271. int param_preprocess(dataptr dz)
  272. {
  273. int exit_status = FINISHED, n;
  274. //TW UPDATE
  275. double x, convertor;
  276. switch(dz->process) {
  277. //TW UPDATE
  278. case(CLICK):
  279. if((exit_status = generate_clicktable(dz))<0)
  280. return(exit_status);
  281. break;
  282. case(SYNTH_WAVE):
  283. case(SYNTH_NOISE):
  284. case(SYNTH_SIL):
  285. break;
  286. case(MULTI_SYN):
  287. convertor = (double)dz->iparam[SYN_TABSIZE] / (double)dz->iparam[SYN_SRATE];
  288. for(n = 0;n<dz->itemcnt;n++)
  289. dz->parray[1][n] *= convertor;
  290. break;
  291. case(SYNTH_SPEC):
  292. x = (dz->param[SS_FOCUS] * 4.0) - 2.0;
  293. dz->param[SS_FOCUS] = pow(10,x);
  294. x = (dz->param[SS_FOCUS2] * 4.0) - 2.0;
  295. dz->param[SS_FOCUS2] = pow(10,x);
  296. break;
  297. default:
  298. sprintf(errstr,"PROGRAMMING PROBLEM: Unknown process in param_preprocess()\n");
  299. return(PROGRAM_ERROR);
  300. }
  301. return(FINISHED);
  302. }
  303. /********************************************************************************************/
  304. /********************************** FORMERLY IN procgrou.c **********************************/
  305. /********************************************************************************************/
  306. /**************************** GROUCHO_PROCESS_FILE ****************************/
  307. int groucho_process_file(dataptr dz) /* FUNCTIONS FOUND IN PROCESS.C */
  308. {
  309. switch(dz->process) {
  310. //TW UPDATE
  311. case(CLICK):
  312. case(SYNTH_WAVE):
  313. case(MULTI_SYN):
  314. case(SYNTH_NOISE):
  315. case(SYNTH_SIL):
  316. return do_synth(dz);
  317. case(SYNTH_SPEC):
  318. return do_stereo_specsynth(dz);
  319. default:
  320. sprintf(errstr,"Unknown case in process_file()\n");
  321. return(PROGRAM_ERROR);
  322. }
  323. return(FINISHED); /* NOTREACHED */
  324. }
  325. /********************************************************************************************/
  326. /********************************** FORMERLY IN pconsistency.c ******************************/
  327. /********************************************************************************************/
  328. /****************************** CHECK_PARAM_VALIDITY_AND_CONSISTENCY *********************************/
  329. int check_param_validity_and_consistency(dataptr dz)
  330. {
  331. int exit_status;
  332. handle_pitch_zeros(dz);
  333. switch(dz->process) {
  334. case(SYNTH_WAVE):
  335. case(MULTI_SYN):
  336. case(SYNTH_NOISE):
  337. case(SYNTH_SIL):
  338. if((exit_status = synth_consistency(dz))<0)
  339. return exit_status;
  340. dz->infile->channels = dz->iparam[SYN_CHANS];
  341. dz->infile->srate = dz->iparam[SYN_SRATE];
  342. dz->infile->stype = SAMP_SHORT;
  343. return create_sized_outfile(dz->wordstor[0],dz);
  344. case(SYNTH_SPEC):
  345. init_specsynth(dz);
  346. //TW UPDATE
  347. return specsynth_consistency(dz);
  348. case(CLICK):
  349. //TW UPDATE
  350. if((exit_status = click_consistency(dz))<0)
  351. return exit_status;
  352. dz->infile->channels = 1;
  353. dz->infile->srate = 44100;
  354. dz->infile->stype = SAMP_SHORT;
  355. return create_sized_outfile(dz->wordstor[0],dz);
  356. }
  357. return(FINISHED);
  358. }
  359. /****************************** SYNTH_CONSISTENCY *********************************/
  360. int synth_consistency(dataptr dz)
  361. {
  362. if(BAD_SR(dz->iparam[SYN_SRATE])) {
  363. sprintf(errstr,"Invalid sample rate.\n");
  364. return(DATA_ERROR);
  365. }
  366. dz->iparam[SYN_TABSIZE] /= 4;
  367. dz->iparam[SYN_TABSIZE] *= 4;
  368. return(FINISHED);
  369. }
  370. /****************************** SPECSYNTH_CONSISTENCY *********************************/
  371. int specsynth_consistency(dataptr dz)
  372. {
  373. if(dz->vflag[SS_PICHSPRD]) {
  374. if(dz->param[SS_SPREAD] > dz->nyquist/SPEC_MINFRQ) {
  375. sprintf(errstr,"SPREAD value is too large for pitch transposition (rather than frq) data.\n");
  376. return(DATA_ERROR);
  377. }
  378. }
  379. return(FINISHED);
  380. }
  381. /********************************************************************************************/
  382. /********************************** FORMERLY IN buffers.c ***********************************/
  383. /********************************************************************************************/
  384. /**************************** ALLOCATE_LARGE_BUFFERS ******************************/
  385. int allocate_large_buffers(dataptr dz)
  386. {
  387. int exit_status, tempchans;
  388. switch(dz->process) {
  389. //TW UPDATE
  390. case(SYNTH_WAVE): case(SYNTH_NOISE): case(SYNTH_SIL): case(CLICK): case(MULTI_SYN):
  391. tempchans = dz->infile->channels;
  392. if(dz->process == CLICK)
  393. dz->infile->channels = 1;
  394. else
  395. dz->infile->channels = dz->iparam[SYN_CHANS];
  396. if((exit_status = create_sndbufs(dz))<0)
  397. return exit_status;
  398. dz->infile->channels = tempchans;
  399. return FINISHED;
  400. case(SYNTH_SPEC):
  401. return allocate_triple_buffer(dz);
  402. default:
  403. sprintf(errstr,"Unknown program no. in allocate_large_buffers()\n");
  404. return(PROGRAM_ERROR);
  405. }
  406. return(FINISHED); /* NOTREACHED */
  407. }
  408. /********************************************************************************************/
  409. /********************************** FORMERLY IN cmdline.c ***********************************/
  410. /********************************************************************************************/
  411. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  412. {
  413. if (!strcmp(prog_identifier_from_cmdline,"wave")) dz->process = SYNTH_WAVE;
  414. else if(!strcmp(prog_identifier_from_cmdline,"noise")) dz->process = SYNTH_NOISE;
  415. else if(!strcmp(prog_identifier_from_cmdline,"silence")) dz->process = SYNTH_SIL;
  416. else if(!strcmp(prog_identifier_from_cmdline,"spectra")) dz->process = SYNTH_SPEC;
  417. else if(!strcmp(prog_identifier_from_cmdline,"clicks")) dz->process = CLICK;
  418. else if(!strcmp(prog_identifier_from_cmdline,"chord")) dz->process = MULTI_SYN;
  419. else {
  420. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  421. return(USAGE_ONLY);
  422. }
  423. //TW UPDATE
  424. return(FINISHED);
  425. }
  426. /********************************************************************************************/
  427. /********************************** FORMERLY IN usage.c *************************************/
  428. /********************************************************************************************/
  429. /******************************** USAGE1 ********************************/
  430. int usage1(void)
  431. {
  432. sprintf(errstr,
  433. "USAGE: synth NAME (mode) outfile parameters\n"
  434. "\n"
  435. "where NAME can be any one of\n"
  436. "\n"
  437. //TW UPDATE
  438. "wave noise silence spectra clicks chord\n"
  439. "\n"
  440. "Type 'synth wave' for more info on synth wave option... ETC.\n");
  441. return(USAGE_ONLY);
  442. }
  443. /******************************** USAGE2 ********************************/
  444. int usage2(char *str)
  445. {
  446. if(!strcmp(str,"wave")) {
  447. sprintf(errstr,
  448. "GENERATE SIMPLE WAVEFORMS\n\n"
  449. "USAGE: synth wave mode outfile sr chans dur freq [-aamp] [-ttabsize]\n\n"
  450. "MODES ARE\n"
  451. "1) sine wave\n"
  452. "2) square wave\n"
  453. "3) sawtooth wave\n"
  454. "4) ramp wave\n\n"
  455. "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
  456. "CHANS can be 1, 2 or 4\n"
  457. "DUR is duration of output snd, in seconds.\n"
  458. "FREQ is frq of output sond, in Hz\n"
  459. "AMP is amplitude of output sound: 0.0 < Range <= 1.0 (max & default).\n"
  460. "TABSIZE is size of table storing waveform.\n"
  461. " defaults to 256: input value always rounded to multiple of 4.\n\n"
  462. "Frq and Amp may vary through time.\n");
  463. } else if(!strcmp(str,"chord")) {
  464. sprintf(errstr,
  465. "GENERATE CHORD ON SIMPLE WAVEFORM\n\n"
  466. "USAGE: synth chord mode outfile datafile sr chans dur [-aamp] [-ttabsize]\n\n"
  467. "MODES ARE\n"
  468. "1) DATAFILE has list of midi data\n"
  469. "2) DATAFILE has list of frequency data\n"
  470. "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
  471. "CHANS can be 1, 2 or 4\n"
  472. "DUR is duration of output snd, in seconds.\n"
  473. "AMP is amplitude of output sound: 0.0 < Range <= 1.0 (max & default).\n"
  474. "TABSIZE is size of table storing waveform.\n"
  475. " defaults to 4096: input value always rounded to multiple of 4.\n\n");
  476. } else if(!strcmp(str,"noise")) {
  477. sprintf(errstr,
  478. "GENERATE NOISE\n\n"
  479. "USAGE: synth noise outfile sr chans dur [-aamp]\n\n"
  480. "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
  481. "CHANS can be 1, 2 or 4\n"
  482. "DUR is duration of output snd, in seconds.\n"
  483. "AMP is amplitude of output sound: 0.0 < Range <= 1.0 (max & default).\n\n"
  484. "Amp may vary through time.\n");
  485. } else if(!strcmp(str,"silence")) {
  486. sprintf(errstr,
  487. "MAKE SILENT SOUNDFILE\n\n"
  488. "USAGE: synth silence outfile sr chans dur\n\n"
  489. "SR (sample rate) can be 48000, 24000, 44100, 22050, 32000, or 16000\n"
  490. "CHANS can be 1, 2 or 4\n"
  491. "DUR is duration of output snd, in seconds.\n");
  492. //TW UPDATE : new options
  493. } else if(!strcmp(str,"spectra")) {
  494. sprintf(errstr,
  495. "GENERATE BOTH CHANNELS OF A STEREO SPECTRAL BAND\n\n"
  496. "USAGE: synth spectra outfilename dur frq spread max-foc min-foc\n"
  497. " timevar srate [-p]\n\n"
  498. "DUR duration of output snd, in seconds.\n"
  499. "FRQ centre frequency of the band.\n"
  500. "SPREAD width of band, in Hz (default) or as transposition ratio.\n"
  501. "'Foc' = focus, degree to which band energy is concentrated at centre frequency.\n"
  502. "MAX-FOC range 0 1\n"
  503. "MIN-FOC range 0 1\n"
  504. "TIMEVAR Degree to which the band varies over time. Range 0-1.\n"
  505. "SRATE Sample rate of output audio file.\n\n"
  506. "-p If flag set, 'SPREAD' is a transposition ratio.\n\n");
  507. } else if(!strcmp(str,"clicks")) {
  508. sprintf(errstr,
  509. "CLICKTRACK USAGE: synth clicks mode outname clickfile [-sstart -eend -zzero]\n\n"
  510. " make clicktrack from 'start' to 'end'; music starting at dataline 'zero'.\n"
  511. " MODE 1: start and end are TIMES: MODE 2: start & end are data linenos.\n"
  512. " CLICKFILE contains sequence of datalines. Each dataline has a line number \n"
  513. " followed by 2, 3 or 4 data items, separated by spaces, which can be....\n"
  514. "TIME 141.52 (Set time to 141.52 secs: must be later than previous event)\n"
  515. "GP 1 23.7 (Pause of 23.7sec, with accent [1] at start: '0' for no accent)\n"
  516. " OR the following set of items:-\n"
  517. "1) TEMPO : in one of the forms (with no spaces around '='):-\n"
  518. " 1=144 (crotchet = 144) 1.5=100 (dotted crotchet = 100)\n"
  519. " 0.5=144to85.3 (tempo change from quaver = 144 to 85.3)\n"
  520. "2) BARRING : in the form 4:4 or 6:8 or 7:16 etc. (no spaces around the ':')\n"
  521. "3) COUNT : i.e. the (integer) number of bars in this format.\n"
  522. "------- and, optionally ---------\n"
  523. "4) ACCENT PATTERN 1..... strong beat followed by 5 weak beats\n"
  524. " 1..1.. strong beat (start), secondary (at 4), weak between\n"
  525. " 100100 strong & secondary beats, but NO intermediate beats\n"
  526. "IF THE ACCENT PATTERN IS OMITTED, default patterns are used. These are:-\n"
  527. "An accent on the start of each bar PLUS\n"
  528. "a) in 6:8, 9:8, 12:8, 15:8 etc, or 6:4, 6:16, 6:32, 9:4, 9:16 etc.\n"
  529. " sound on every unit (4,8,16,32 etc.), secondary accents every 3rd beat\n"
  530. "b) in All other meters: NO secondary accents\n");
  531. } else
  532. sprintf(errstr,"Unknown option '%s'\n",str);
  533. return(USAGE_ONLY);
  534. }
  535. /******************************** USAGE3 ********************************/
  536. int usage3(char *str1,char *str2)
  537. {
  538. sprintf(errstr,"Insufficient parameters on command line.\n");
  539. return(USAGE_ONLY);
  540. }
  541. /******************************** INNER_LOOP (redundant) ********************************/
  542. int inner_loop
  543. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  544. {
  545. return(FINISHED);
  546. }
  547. /******************************** INIT_SPECSYNTH (redundant) ********************************/
  548. void init_specsynth(dataptr dz)
  549. {
  550. //TW Extensive rewrite
  551. dz->outfile->origrate = dz->infile->origrate = (int)round(dz->param[SS_SRATE]);
  552. if(dz->floatsam_output) {
  553. dz->outfile->stype = SAMP_FLOAT;
  554. dz->infile->stype = SAMP_FLOAT;
  555. dz->outfile->origstype = SAMP_FLOAT;
  556. dz->infile->origstype = SAMP_FLOAT;
  557. } else {
  558. dz->outfile->origstype = SAMP_SHORT;
  559. dz->infile->origstype = SAMP_SHORT;
  560. dz->outfile->stype = SAMP_SHORT;
  561. dz->infile->stype = SAMP_SHORT;
  562. }
  563. dz->wanted = SPECSYN_MLEN;
  564. dz->outfile->channels = SPECSYN_MLEN;
  565. dz->infile->channels = SPECSYN_MLEN;
  566. dz->outfile->Mlen = dz->infile->Mlen = (dz->outfile->channels-2);
  567. dz->wanted = dz->infile->channels;
  568. dz->clength = dz->wanted/2;
  569. dz->nyquist = dz->outfile->origrate / 2;
  570. dz->outfile->Dfac = dz->infile->Dfac = (dz->outfile->channels-2) / 8;
  571. dz->outfile->arate = dz->infile->arate = (float) dz->outfile->origrate / (float)dz->outfile->Dfac;
  572. dz->outfile->srate = dz->infile->srate = (int) dz->outfile->arate;
  573. dz->frametime = (float)(1.0/dz->outfile->arate);
  574. dz->wlength = (int)round(dz->param[SS_DUR] * dz->outfile->arate);
  575. dz->chwidth = dz->nyquist/(double)dz->clength;
  576. }
  577. //TW UPDATE : NEW FUNCTIONS below
  578. /******************************** READ_CLICKTRACK_DATA ********************************/
  579. #define CLICKLINE (0)
  580. #define CLICKTEMPO (1)
  581. #define CLICKMETER (2)
  582. #define CLICKCOUNT (3)
  583. #define CLICKSTYLE (4)
  584. int read_clicktrack_data(char *str,dataptr dz)
  585. {
  586. int exit_status, init = 1;
  587. int cnt, linecnt = 0, GP, is_abstime, accent;
  588. char temp[200], *q, *p;
  589. int arraysize = BIGARRAY * 10, tarray = BIGARRAY * 10, tcnt = 0;/* ARRAYS V. BIG AS free() fails inside realloc() or on its own */
  590. double tempo = -1.0, accel = -1.0, time = 0.0, pulse_unit = 0.0, timeincr, lasttime = -HUGE, abstime = 0.0;
  591. int metre_num = -1, metre_denom = 1, barcnt = 0;
  592. char style[200];
  593. double mintimestep = 0.0;
  594. FILE *fp;
  595. if((fp = fopen(str,"r"))==NULL) {
  596. sprintf(errstr,"Cannot open clicktrack data file %s\n",str);
  597. return(DATA_ERROR);
  598. }
  599. while(fgets(temp,200,fp)!=NULL) { /* READ AND TEST BRKPNT VALS */
  600. q = temp;
  601. cnt = 0;
  602. while(isspace(*q))
  603. q++;
  604. GP = 0;
  605. is_abstime = 0;
  606. accent = 0;
  607. timeincr = 0.0;
  608. if(*q == ENDOFSTR || *q == ';') /* ignore blank lines and comments */
  609. continue;
  610. while(get_word_from_string(&q,&p)) {
  611. switch(cnt) {
  612. case(CLICKLINE):
  613. if((exit_status = getlineno(p,tcnt+1,linecnt+1)) < 0)
  614. return(exit_status);
  615. break;
  616. case(CLICKTEMPO):
  617. if((exit_status = gettempo(p,&tempo,&pulse_unit,&accel,linecnt,&GP,&is_abstime)) < 0)
  618. return(exit_status);
  619. break;
  620. case(CLICKMETER):
  621. if((exit_status = getmeter(p,&metre_num,&metre_denom,linecnt,GP,is_abstime,&abstime,&accent)) < 0)
  622. return(exit_status);
  623. break;
  624. case(CLICKCOUNT):
  625. if((exit_status = getcount(p,&barcnt,linecnt,GP,is_abstime,&timeincr)) < 0)
  626. return(exit_status);
  627. break;
  628. case(CLICKSTYLE):
  629. if((exit_status = getstyle(p,style,metre_num,linecnt,GP,is_abstime)) < 0)
  630. return(exit_status);
  631. break;
  632. default:
  633. sprintf(errstr,"Too many data items on line %d\n",linecnt+1);
  634. return(DATA_ERROR);
  635. }
  636. cnt++;
  637. }
  638. if(cnt < 5) {
  639. switch(cnt) {
  640. case(3):
  641. if(!is_abstime) {
  642. sprintf(errstr,"Too few data items on line %d\n",linecnt+1);
  643. return(DATA_ERROR);
  644. }
  645. break;
  646. case(4):
  647. if(!GP && ((exit_status = default_style(style,metre_num)) < 0))
  648. return(exit_status);
  649. break;
  650. default:
  651. sprintf(errstr,"Too few data items on line %d\n",linecnt+1);
  652. return(DATA_ERROR);
  653. }
  654. }
  655. if ((exit_status = generate_clickdata(init,&arraysize,tempo,pulse_unit,metre_num,metre_denom,style,barcnt,
  656. accel,&time,&lasttime,GP,is_abstime,abstime,accent,timeincr,&tcnt,&tarray,&mintimestep,dz)) < 0)
  657. return(exit_status);
  658. init = 0;
  659. linecnt++;
  660. }
  661. dz->parray[2][tcnt] = lasttime;
  662. dz->iparam[CLICKTIME] = linecnt;
  663. dz->duration = (double)linecnt; /* tells cdparams about range of param 3 */
  664. return(FINISHED);
  665. }
  666. /******************************** READ_CHORD_DATA ********************************/
  667. int read_chord_data(char *str,dataptr dz)
  668. {
  669. int cnt = 0, exit_status;
  670. char temp[200], *q;
  671. double maxmidi = 127.0, minmidi;
  672. double maxfrq = miditohz(127);
  673. double minfrq = 1.0/MAX_SYN_DUR;
  674. double d;
  675. FILE *fp;
  676. if((exit_status = hztomidi(&minmidi,minfrq)) < 0)
  677. return exit_status;
  678. if((fp = fopen(str,"r"))==NULL) {
  679. sprintf(errstr,"Cannot open chord data file %s\n",str);
  680. return(DATA_ERROR);
  681. }
  682. dz->ringsize = 1;
  683. while(fgets(temp,200,fp)!=NULL) { /* READ AND TEST BRKPNT VALS */
  684. q = temp;
  685. while(get_float_from_within_string(&q,&d)) {
  686. switch(dz->mode) {
  687. case(0): /* MIDI */
  688. if(d < minmidi || d > maxmidi) {
  689. sprintf(errstr,"Value %d (%lf) is out of range.\n",cnt+1,d);
  690. return(DATA_ERROR);
  691. }
  692. break;
  693. case(1): /* FRQ */
  694. if(d < minfrq || d > maxfrq) {
  695. sprintf(errstr,"Value %d (%lf) is out of range.\n",cnt+1,d);
  696. return(DATA_ERROR);
  697. }
  698. break;
  699. case(2): /* MIDI, CHORD SEQUENCE */
  700. if(d < -99.0)
  701. dz->ringsize++;
  702. else if(d < minmidi || d > maxmidi) {
  703. sprintf(errstr,"Value %d (%lf) is out of range.\n",cnt+1,d);
  704. return(DATA_ERROR);
  705. }
  706. break;
  707. }
  708. cnt++;
  709. }
  710. }
  711. if(cnt == 0) {
  712. sprintf(errstr,"No data found in file.\n");
  713. return(MEMORY_ERROR);
  714. }
  715. if((dz->parray[1] = (double *)malloc(cnt * sizeof(double)))==NULL) {
  716. sprintf(errstr,"Insufficient memory to store MIDI values.\n");
  717. return(MEMORY_ERROR);
  718. }
  719. if((dz->parray[2] = (double *)malloc(cnt * sizeof(double)))==NULL) {
  720. sprintf(errstr,"Insufficient memory to store table step values.\n");
  721. return(MEMORY_ERROR);
  722. }
  723. if((dz->parray[3] = (double *)malloc(cnt * sizeof(double)))==NULL) {
  724. sprintf(errstr,"Insufficient memory to store sample interpolators.\n");
  725. return(MEMORY_ERROR);
  726. }
  727. if((dz->lparray[0] = (int *)malloc(cnt * sizeof(int)))==NULL) {
  728. sprintf(errstr,"Insufficient memory to store samplecounters.\n");
  729. return(MEMORY_ERROR);
  730. }
  731. fseek(fp,0,0);
  732. cnt = 0;
  733. while(fgets(temp,200,fp)!=NULL) { /* READ AND TEST BRKPNT VALS */
  734. q = temp;
  735. while(get_float_from_within_string(&q,&d)) {
  736. switch(dz->mode) {
  737. case(0):
  738. d = miditohz(d);
  739. break;
  740. case(2):
  741. if(d < -99.0)
  742. d = 0.0;
  743. else
  744. d = miditohz(d);
  745. break;
  746. }
  747. dz->parray[1][cnt] = d;
  748. cnt++;
  749. }
  750. }
  751. dz->itemcnt = cnt;
  752. for(cnt=0;cnt<dz->itemcnt;cnt++) {
  753. dz->parray[2][cnt] = 0.0; /* initialise all table increments and positions */
  754. dz->parray[3][cnt] = 0.0;
  755. dz->lparray[0][cnt] = 0;
  756. }
  757. return(FINISHED);
  758. }
  759. /*********************************** GETTEMPO ***********************************
  760. *
  761. * Expected format 1=144 OR 1.5=134.567 [or "G" (or "g") as part of "G P"]
  762. */
  763. int gettempo(char *str,double *tempo,double *pulse_unit,double *accel,int linecnt,int *GP,int *is_abstime)
  764. {
  765. char *p;
  766. p = str;
  767. if(!strcmp(str,"GP")) {
  768. *GP = 1;
  769. return(FINISHED);
  770. } else if(!strcmp(str,"TIME")) {
  771. if(linecnt == 0) {
  772. sprintf(errstr,"'TIME' dataline too soon: You cannot reset the Absolute time before you start the clickdata.\n");
  773. return(DATA_ERROR);
  774. }
  775. *is_abstime = 1;
  776. return(FINISHED);
  777. } else if(!strcmp(str,".")) {
  778. if(*accel >= 0.0) {
  779. sprintf(errstr,"Bad tempo data at line %d : Cannot use a DOT (for same tempo) when previous tempo was changing\n",linecnt+1);
  780. return(DATA_ERROR);
  781. } else if(*tempo < 0.0) {
  782. sprintf(errstr,"Bad tempo data at line %d : Cannot use a DOT (for same tempo) when no previous tempo established\n",linecnt+1);
  783. return(DATA_ERROR);
  784. }
  785. return(FINISHED);
  786. }
  787. if(!strgetfloat_within_string(&p,pulse_unit)) {
  788. sprintf(errstr,"Bad tempo data at line %d : Cannot get length of pulse unit (e.g. 1 = crotchet)\n",linecnt+1);
  789. return(DATA_ERROR);
  790. }
  791. if(!flteq(*pulse_unit,1.0) && !flteq(*pulse_unit,2.0) && !flteq(*pulse_unit,3.0) && !flteq(*pulse_unit,4.0)
  792. && !flteq(*pulse_unit,1.5) && !flteq(*pulse_unit,0.75) && !flteq(*pulse_unit,0.375) && !flteq(*pulse_unit,0.1875)
  793. && !flteq(*pulse_unit,0.5) && !flteq(*pulse_unit,0.25) && !flteq(*pulse_unit,0.125)) {
  794. sprintf(errstr,"Bad tempo data at line %d : Invalid pulse unit (%.3lf)\n",linecnt+1,*pulse_unit);
  795. return(DATA_ERROR);
  796. }
  797. if(*p++ != '=') {
  798. sprintf(errstr,"Bad tempo data at line %d : '=' missing, or spaces before '='\n",linecnt+1);
  799. return(DATA_ERROR);
  800. }
  801. if(!strgetfloat_within_string(&p,tempo)) {
  802. sprintf(errstr,"Bad tempo data at line %d : Failed to find metronome mark value\n",linecnt+1);
  803. return(DATA_ERROR);
  804. }
  805. *accel = -1.0;
  806. if(strlen(p) > 0) {
  807. if(!strncmp(p,"to",2)) {
  808. p += 2;
  809. if(!strgetfloat_within_string(&p,accel)) {
  810. sprintf(errstr,"Bad tempo data at line %d : Failed to find tempo at end of tempo-change\n",linecnt+1);
  811. return(DATA_ERROR);
  812. }
  813. } else {
  814. sprintf(errstr,"Bad tempo data at line %d : Spurious characters at end (can be 'to' followed by 2nd tempo only)\n",linecnt+1);
  815. return(DATA_ERROR);
  816. }
  817. }
  818. return(FINISHED);
  819. }
  820. /*********************************** GETMETER ***********************************
  821. *
  822. * Expected format 3:8, [OR P (or p) as part of "G P"]
  823. */
  824. int getmeter(char *str,int *metre_num,int *metre_denom,int linecnt,int GP,int is_abstime,double *abstime,int *accent)
  825. {
  826. char *q,*p = str;
  827. int k, j;
  828. if(GP) {
  829. if(!strcmp(str,"1")) {
  830. *accent = 1;
  831. return(FINISHED);
  832. } else if(!strcmp(str,"0"))
  833. return(FINISHED);
  834. else {
  835. sprintf(errstr,"Bad GP data at line %d : no accent indicator (0 or 1)\n",linecnt+1);
  836. return(DATA_ERROR);
  837. }
  838. } else if(is_abstime) {
  839. if(sscanf(str,"%lf",abstime)!=1) {
  840. sprintf(errstr,"Bad TIME data at line %d (found '%s')\n",linecnt+1,str);
  841. return(DATA_ERROR);
  842. }
  843. return(FINISHED);
  844. } else if(!strcmp(str,".")) {
  845. if(*metre_num < 0) {
  846. sprintf(errstr,"Bad meter data at line %d : Cannot use a DOT (for same meter) when no previous meter exists\n",linecnt+1);
  847. return(DATA_ERROR);
  848. }
  849. return(FINISHED);
  850. }
  851. while(*p != ':') {
  852. if(!isdigit(*p)) {
  853. sprintf(errstr,"Bad meter data at line %d : no numerator, or non-numeric character or space in numerator before ':' or missing ':'\n",linecnt+1);
  854. return(DATA_ERROR);
  855. }
  856. p++;
  857. }
  858. *p = ENDOFSTR;
  859. if(sscanf(str,"%d",metre_num)!=1) {
  860. sprintf(errstr,"Bad meter data at line %d : Failed to find numerator of meter\n",linecnt+1);
  861. return(DATA_ERROR);
  862. }
  863. p++;
  864. q = p;
  865. while(*p != ENDOFSTR) {
  866. if(!isdigit(*p)) {
  867. sprintf(errstr,"Bad meter data at line %d : non-numeric (or no) characters after ':'\n",linecnt+1);
  868. return(DATA_ERROR);
  869. }
  870. p++;
  871. }
  872. if(sscanf(q,"%d",metre_denom)!=1) {
  873. sprintf(errstr,"Bad meter data at line %d : Failed to find denominator of meter (no spaces permitted after ':')\n",linecnt+1);
  874. return(DATA_ERROR);
  875. }
  876. if((k = *metre_denom) < 2) {
  877. sprintf(errstr,"Bad meter data at line %d : denominator of meter is not a multiple of 2\n",linecnt+1);
  878. return(DATA_ERROR);
  879. }
  880. while(k > 2) {
  881. j = k/2;
  882. if(k != j * 2) {
  883. sprintf(errstr,"Bad meter data at line %d : denominator of meter is not a multiple of 2\n",linecnt+1);
  884. return(DATA_ERROR);
  885. }
  886. k = j;
  887. }
  888. return(FINISHED);
  889. }
  890. /*********************************** GETSTYLE ***********************************************
  891. *
  892. * Expected format 1..... or 1..1.. or 100100 where number of chars = denominator of meter
  893. */
  894. int getstyle(char *str,char *style,int metre_num,int linecnt,int GP,int is_abstime)
  895. {
  896. char *p = str;
  897. if(GP || is_abstime)
  898. return(FINISHED);
  899. while(*p != ENDOFSTR) {
  900. if(*p != '1' && *p != '.' && *p != '0') {
  901. sprintf(errstr,"Bad style data at line %d : Invalid character (%c) in style string (must be '1','0' or '.'\n",linecnt+1,*p);
  902. return(DATA_ERROR);
  903. }
  904. p++;
  905. }
  906. if((p - str) != metre_num) {
  907. sprintf(errstr,"Bad style data at line %d : Wrong number of characters in style-string (must be %d in this meter)\n",linecnt+1,metre_num);
  908. return(DATA_ERROR);
  909. }
  910. strcpy(style,str);
  911. return(FINISHED);
  912. }
  913. /*********************************** GETLINENO ***********************************************
  914. *
  915. * Expected format = digit (increasing from 1)
  916. */
  917. int getlineno(char *str,int tcnt,int linecnt)
  918. {
  919. int lineno;
  920. if(sscanf(str,"%d",&lineno)!=1) {
  921. sprintf(errstr,"Failed to read line number, at line %d (found '%s')\n",linecnt,str);
  922. return(DATA_ERROR);
  923. }
  924. if(lineno != linecnt) {
  925. if(lineno == 0) {
  926. sprintf(errstr,"Lines should be numbered from 1 upwards\n");
  927. return(DATA_ERROR);
  928. } else {
  929. sprintf(errstr,"Line numbers are not in sequence, at line %d\n",linecnt);
  930. return(DATA_ERROR);
  931. }
  932. }
  933. if(lineno != tcnt) {
  934. sprintf(errstr,"Anomaly in counting lines, at line %d\n",linecnt);
  935. return(PROGRAM_ERROR);
  936. }
  937. return(FINISHED);
  938. }
  939. /*********************************** GETCOUNT ***********************************************
  940. *
  941. * Expected format is an INTEGER
  942. */
  943. int getcount(char *str,int *barcnt,int linecnt,int GP,int is_abstime,double *timeincr)
  944. {
  945. char *p = str;
  946. if(is_abstime)
  947. return(FINISHED);
  948. else if(GP) {
  949. if(sscanf(str,"%lf",timeincr)!=1) {
  950. sprintf(errstr,"Failed to read duration of General Pause at line %d\n",linecnt+1);
  951. return(DATA_ERROR);
  952. }
  953. return(FINISHED);
  954. }
  955. while(*p != ENDOFSTR) {
  956. if(!isdigit(*p)) {
  957. sprintf(errstr,"Bad bar-count data at line %d : Non-numeric character encountered (must be whole number of bars)\n",linecnt+1);
  958. return(DATA_ERROR);
  959. }
  960. p++;
  961. }
  962. if(sscanf(str,"%d",barcnt)!=1) {
  963. sprintf(errstr,"Bad bar-count data at line %d : Failed to read bar-count\n",linecnt+1);
  964. return(DATA_ERROR);
  965. }
  966. if(*barcnt < 1) {
  967. sprintf(errstr,"Bad bar-count (%d) data at line %d\n",*barcnt,linecnt+1);
  968. return(DATA_ERROR);
  969. }
  970. return(FINISHED);
  971. }
  972. /*********************************** GENERATE_CLICKDATA ***********************************************/
  973. #define ACCELPOW (0.6)
  974. #define RITPOW (1.0/ACCELPOW)
  975. int generate_clickdata
  976. (int init,int *arraysize,double tempo,double pulse_unit,int metre_num,int metre_denom,char *style,int barcnt,double accel,
  977. double *time,double *lasttime,int GP,int is_abstime,double abstime,int accent,double timeincr,int *tcnt,int *tarray,
  978. double *mintimestep,dataptr dz)
  979. {
  980. int n, eventcnt;
  981. double timestep, unit_tempo, *cliks, pulse_mutiplier;
  982. double orig_timestep = 0.0, final_timestep, total_beats = 1.0, tstepinc = 0.0, thisincr;
  983. char *p = style;
  984. int do_accel, steptype = 1;
  985. if(init) {
  986. if((dz->parray[0] = (double *)malloc(*arraysize * sizeof(double)))==NULL) {
  987. sprintf(errstr,"INSUFFICIENT MEMORY to make clicktrack data array.\n");
  988. return(MEMORY_ERROR);
  989. }
  990. dz->itemcnt = 0;
  991. *mintimestep = (double)((CLICKLEN + 1) + 4 /* safety */)/(double)dz->infile->srate;
  992. if((dz->parray[2] = (double *)malloc(*tarray * sizeof(double)))==NULL) {
  993. sprintf(errstr,"INSUFFICIENT MEMORY to store clicktrack data line times.\n");
  994. return(MEMORY_ERROR);
  995. }
  996. }
  997. cliks = dz->parray[0];
  998. dz->parray[2][(*tcnt)++] = *time;
  999. if(*tcnt > *tarray) {
  1000. *tarray += BIGARRAY;
  1001. if((dz->parray[2] = (double *)realloc((char *)dz->parray[2],(*tarray) * sizeof(double)))==NULL) {
  1002. sprintf(errstr,"INSUFFICIENT MEMORY to store clicktrack data line times.\n");
  1003. return(MEMORY_ERROR);
  1004. }
  1005. }
  1006. if(GP) {
  1007. if(accent) {
  1008. if(dz->itemcnt + 2 >= *arraysize) {
  1009. *arraysize += BIGARRAY;
  1010. if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],*arraysize * sizeof(double)))==NULL) {
  1011. sprintf(errstr,"INSUFFICIENT MEMORY to make expand clicktrack data array.\n");
  1012. return(MEMORY_ERROR);
  1013. }
  1014. cliks = dz->parray[0];
  1015. }
  1016. cliks[dz->itemcnt++] = *time;
  1017. cliks[dz->itemcnt++] = CLICKAMP1;
  1018. }
  1019. *lasttime = *time;
  1020. *time += timeincr;
  1021. return(FINISHED);
  1022. }
  1023. if(is_abstime) {
  1024. if(abstime < *lasttime) {
  1025. sprintf(errstr,"ABSOLUTE TIME %lf is OUT OF SEQUENCE.\n",abstime); /*RWD 12:2003 added abstime arg */
  1026. return(DATA_ERROR);
  1027. }
  1028. *time = abstime;
  1029. return(FINISHED);
  1030. }
  1031. pulse_mutiplier = (double)metre_denom/4.0; /* could be .5 if beats are minims */
  1032. unit_tempo = tempo * pulse_unit; /* crotchets per minute */
  1033. unit_tempo *= pulse_mutiplier; /* basic pulse-divisions per minute */
  1034. unit_tempo /= 60.0; /* basic pulse-divisions per second */
  1035. if((timestep = (1.0/unit_tempo)) < *mintimestep) {
  1036. sprintf(errstr,"Tempo too fast to separate clicks in output, at time %lf secs.\n",*time);
  1037. return(DATA_ERROR);
  1038. }
  1039. eventcnt = 0;
  1040. if(accel > 0.0) { /* in accel or rit case, change tempo logwise */
  1041. if((final_timestep = timestep * (tempo/accel)) < *mintimestep) {
  1042. sprintf(errstr,"Tempo too fast to separate clicks in output, at time %lf secs.\n",*time);
  1043. return(DATA_ERROR);
  1044. }
  1045. total_beats = barcnt * metre_num;
  1046. if((tstepinc = final_timestep - timestep) < 0) {
  1047. steptype = -1;
  1048. tstepinc = -tstepinc;
  1049. }
  1050. orig_timestep = timestep;
  1051. do_accel = 1;
  1052. } else
  1053. do_accel = 0;
  1054. for(n = 0; n < barcnt; n++) { /* for each bar */
  1055. if(dz->itemcnt + (metre_num * 2) >= *arraysize) {
  1056. *arraysize += BIGARRAY;
  1057. if((dz->parray[0] = (double *)realloc((char *)dz->parray[0],*arraysize * sizeof(double)))==NULL) {
  1058. sprintf(errstr,"INSUFFICIENT MEMORY to make expand clicktrack data array.\n");
  1059. return(MEMORY_ERROR);
  1060. }
  1061. cliks = dz->parray[0];
  1062. }
  1063. while(*p != ENDOFSTR) { /* for each beat in specified pattern */
  1064. switch(*p) {
  1065. case('1'):
  1066. cliks[dz->itemcnt++] = *time;
  1067. if(p == style) /* stress first beat */
  1068. cliks[dz->itemcnt++] = CLICKAMP1;
  1069. else /* half-stress subsidiary accents */
  1070. cliks[dz->itemcnt++] = CLICKAMP2;
  1071. break;
  1072. case('.'): /* sound other beats with no stress */
  1073. cliks[dz->itemcnt++] = *time;
  1074. cliks[dz->itemcnt++] = CLICKAMP3;
  1075. break;
  1076. /* case('0'): ignore unsounded beats */
  1077. }
  1078. if(do_accel) { /* if tempo changing, increment timestep logwise */
  1079. if(steptype < 0)
  1080. thisincr = pow(((double)eventcnt/(double)total_beats),ACCELPOW) * tstepinc * steptype;
  1081. else
  1082. thisincr = pow(((double)eventcnt/(double)total_beats),RITPOW) * tstepinc * steptype;
  1083. timestep = orig_timestep + thisincr;
  1084. eventcnt++;
  1085. }
  1086. *lasttime = *time;
  1087. *time += timestep; /* advance absolute time to next beat */
  1088. p++; /* advance along accent pattern */
  1089. }
  1090. p = style; /* at end of pattern, return to start of pattern */
  1091. }
  1092. return(FINISHED);
  1093. }
  1094. /*********************************** DEFAULT_STYLE ***********************************************/
  1095. int default_style(char *style,int metre_num)
  1096. {
  1097. char *p = style;
  1098. int triple = 0, n;
  1099. if((((metre_num/3) * 3) == metre_num) && (metre_num > 3))
  1100. triple = 1;
  1101. *p++ = '1';
  1102. for(n = 1; n < metre_num;n++) {
  1103. if(triple & (n%3 == 0))
  1104. *p = '1';
  1105. else
  1106. *p = '.';
  1107. p++;
  1108. }
  1109. *p = ENDOFSTR;
  1110. return(FINISHED);
  1111. }
  1112. /*********************************** GENERATE_CLICKTABLE ***********************************************/
  1113. int generate_clicktable(dataptr dz)
  1114. {
  1115. int n;
  1116. double rand1, rand2, maxval;
  1117. if((dz->parray[1] = (double *)malloc((CLICKLEN +1) * sizeof(double)))==NULL) {
  1118. sprintf(errstr,"INSUFFICIENT MEMORY to store click table.\n");
  1119. return(MEMORY_ERROR);
  1120. }
  1121. initrand48();
  1122. maxval = 0.0;
  1123. for(n=0;n < CLICKLEN;n++) {
  1124. rand1 = (drand48() * 2.0) - 1.0; /* in case I decide to modify it every time !! */
  1125. rand2 = (drand48() * .02) - .01;
  1126. dz->parray[1][n] = sqrt(sin(PI/(double)n)) * ((double)n * 2.0 * PI/(6.0+ rand1)) * rand2 * (MAXSHORT * .98);
  1127. /* 1/2 sin envel, steepened * sin oscil every 6 or so samps * noise * maxsamp adjusted for noise wander */
  1128. maxval= max(maxval,fabs(dz->parray[1][n]));
  1129. }
  1130. maxval = MAXSHORT/maxval;
  1131. for(n=0;n < CLICKLEN;n++)
  1132. dz->parray[1][n] *= maxval;
  1133. dz->parray[1][n] = 0.0;
  1134. return(FINISHED);
  1135. }
  1136. /*********************************** CLICK_CONSISTENCY ***********************************************/
  1137. int click_consistency(dataptr dz)
  1138. {
  1139. double lasttime;
  1140. switch(dz->mode) {
  1141. case(CLICK_BY_TIME):
  1142. if(dz->param[CLIKSTART] >= dz->param[CLIKEND]) {
  1143. sprintf(errstr,"Start time for Click Generation is beyond End time.\n");
  1144. return(DATA_ERROR);
  1145. }
  1146. lasttime = dz->parray[0][dz->itemcnt - 2];
  1147. if(dz->param[CLIKSTART] > lasttime - FLTERR) {
  1148. sprintf(errstr,"Start time for Click Generation is beyond end of your data.\n");
  1149. return(DATA_ERROR);
  1150. }
  1151. dz->param[CLIKEND] = min(dz->param[CLIKEND],lasttime);
  1152. break;
  1153. case(CLICK_BY_LINE):
  1154. if(dz->iparam[CLIKSTART] > dz->iparam[CLIKEND]) {
  1155. sprintf(errstr,"Start line for Click Generation is at or beyond End line.\n");
  1156. return(DATA_ERROR);
  1157. }
  1158. if(dz->iparam[CLIKSTART] > dz->iparam[CLICKTIME]) {
  1159. sprintf(errstr,"Start line for Click Generation is beyond end of your data.\n");
  1160. return(DATA_ERROR);
  1161. }
  1162. dz->iparam[CLIKSTART]--;
  1163. dz->iparam[CLIKEND]--;
  1164. dz->iparam[CLIKEND] = min(dz->iparam[CLIKEND],(dz->iparam[CLICKTIME] - 1));
  1165. break;
  1166. }
  1167. dz->iparam[CLIKOFSET]--; /* convert from "1-N" to "0 to N-1" */
  1168. return(FINISHED);
  1169. }