crumble.c 87 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987
  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 <structures.h>
  24. #include <tkglobals.h>
  25. #include <pnames.h>
  26. #include <filetype.h>
  27. #include <processno.h>
  28. #include <modeno.h>
  29. #include <logic.h>
  30. #include <globcon.h>
  31. #include <cdpmain.h>
  32. #include <math.h>
  33. #include <mixxcon.h>
  34. #include <osbind.h>
  35. #include <standalone.h>
  36. #include <science.h>
  37. #include <ctype.h>
  38. #include <sfsys.h>
  39. #include <string.h>
  40. #include <srates.h>
  41. #ifdef unix
  42. #define round(x) lround((x))
  43. #endif
  44. char errstr[2400];
  45. #define maxinseg rampbrksize
  46. #define maxoutseg temp_sampsize
  47. #define splicelen ringsize
  48. #define warned zeroset
  49. #define hastail fzeroset
  50. #define notailanywhere is_mapping
  51. #define SAFETY 4
  52. int anal_infiles = 1;
  53. int sloom = 0;
  54. int sloombatch = 0;
  55. const char* cdp_version = "7.0.1";
  56. //CDP LIB REPLACEMENTS
  57. static int setup_crumble_application(dataptr dz);
  58. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  59. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  60. static int setup_crumble_param_ranges_and_defaults(dataptr dz);
  61. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
  62. static int open_the_outfile(dataptr dz);
  63. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  64. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  65. static int establish_application(dataptr dz);
  66. static int initialise_vflags(dataptr dz);
  67. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  68. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  69. static int mark_parameter_types(dataptr dz,aplptr ap);
  70. static int assign_file_data_storage(int infilecnt,dataptr dz);
  71. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  72. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  73. static int get_the_mode_from_cmdline(char *str,dataptr dz);
  74. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  75. static int check_crumble_param_validity_and_consistency(dataptr dz);
  76. static int create_crumble_sndbufs(dataptr dz);
  77. static void shuflup(int *perm,int permsize,int k);
  78. static void prefix(int *perm,int permsize,int n);
  79. static void insert(int *perm,int permsize,int n,int t);
  80. static void doperm(int *perm,int permsize,int *lastperm,int *lastperm2);
  81. static int crumble(dataptr dz);
  82. /**************************************** MAIN *********************************************/
  83. int main(int argc,char *argv[])
  84. {
  85. int exit_status;
  86. dataptr dz = NULL;
  87. char **cmdline;
  88. int cmdlinecnt;
  89. int n;
  90. // aplptr ap;
  91. int is_launched = FALSE;
  92. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  93. fprintf(stdout,"%s\n",cdp_version);
  94. fflush(stdout);
  95. return 0;
  96. }
  97. /* CHECK FOR SOUNDLOOM */
  98. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  99. sloom = 0;
  100. sloombatch = 1;
  101. }
  102. if(sflinit("cdp")){
  103. sfperror("cdp: initialisation\n");
  104. return(FAILED);
  105. }
  106. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  107. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  108. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  109. return(FAILED);
  110. }
  111. if(!sloom) {
  112. if(argc == 1) {
  113. usage1();
  114. return(FAILED);
  115. } else if(argc == 2) {
  116. usage2(argv[1]);
  117. return(FAILED);
  118. }
  119. }
  120. if(!sloom) {
  121. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  122. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  123. return(FAILED);
  124. }
  125. cmdline = argv;
  126. cmdlinecnt = argc;
  127. if((get_the_process_no(argv[0],dz))<0)
  128. return(FAILED);
  129. cmdline++;
  130. cmdlinecnt--;
  131. dz->maxmode = 2;
  132. if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
  133. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  134. return(exit_status);
  135. }
  136. cmdline++;
  137. cmdlinecnt--;
  138. // setup_particular_application =
  139. if((exit_status = setup_crumble_application(dz))<0) {
  140. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  141. return(FAILED);
  142. }
  143. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  144. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  145. return(FAILED);
  146. }
  147. } else {
  148. //parse_TK_data() =
  149. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  150. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  151. return(exit_status);
  152. }
  153. }
  154. // ap = dz->application;
  155. // parse_infile_and_hone_type() =
  156. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  157. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  158. return(FAILED);
  159. }
  160. // setup_param_ranges_and_defaults() =
  161. if((exit_status = setup_crumble_param_ranges_and_defaults(dz))<0) {
  162. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  163. return(FAILED);
  164. }
  165. // open_first_infile CDP LIB
  166. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  167. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  168. return(FAILED);
  169. }
  170. cmdlinecnt--;
  171. cmdline++;
  172. // handle_extra_infiles() : redundant
  173. // handle_outfile() =
  174. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
  175. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  176. return(FAILED);
  177. }
  178. // handle_formants() redundant
  179. // handle_formant_quiksearch() redundant
  180. // handle_special_data() redundant
  181. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  182. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  183. return(FAILED);
  184. }
  185. // check_param_validity_and_consistency ....
  186. if((exit_status = check_crumble_param_validity_and_consistency(dz))<0) {
  187. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  188. return(FAILED);
  189. }
  190. is_launched = TRUE;
  191. dz->bufcnt = 5;
  192. if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
  193. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
  194. return(MEMORY_ERROR);
  195. }
  196. if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
  197. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
  198. return(MEMORY_ERROR);
  199. }
  200. for(n = 0;n <dz->bufcnt; n++)
  201. dz->sampbuf[n] = dz->sbufptr[n] = (float *)0;
  202. dz->sampbuf[n] = (float *)0;
  203. // create_sndbufs .....
  204. if((exit_status = create_crumble_sndbufs(dz))<0) {
  205. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  206. return(FAILED);
  207. }
  208. //param_preprocess() redundant
  209. //spec_process_file =
  210. if((exit_status = open_the_outfile(dz))<0) {
  211. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  212. return(FAILED);
  213. }
  214. if((exit_status = crumble(dz))<0) {
  215. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  216. return(FAILED);
  217. }
  218. if((exit_status = complete_output(dz))<0) { // CDP LIB
  219. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  220. return(FAILED);
  221. }
  222. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  223. free(dz);
  224. return(SUCCEEDED);
  225. }
  226. /**********************************************
  227. REPLACED CDP LIB FUNCTIONS
  228. **********************************************/
  229. /****************************** SET_PARAM_DATA *********************************/
  230. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  231. {
  232. ap->special_data = (char)special_data;
  233. ap->param_cnt = (char)paramcnt;
  234. ap->max_param_cnt = (char)maxparamcnt;
  235. if(ap->max_param_cnt>0) {
  236. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  237. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  238. return(MEMORY_ERROR);
  239. }
  240. strcpy(ap->param_list,paramlist);
  241. }
  242. return(FINISHED);
  243. }
  244. /****************************** SET_VFLGS *********************************/
  245. int set_vflgs
  246. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  247. {
  248. ap->option_cnt = (char) optcnt; /*RWD added cast */
  249. if(optcnt) {
  250. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  251. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  252. return(MEMORY_ERROR);
  253. }
  254. strcpy(ap->option_list,optlist);
  255. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  256. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  257. return(MEMORY_ERROR);
  258. }
  259. strcpy(ap->option_flags,optflags);
  260. }
  261. ap->vflag_cnt = (char) vflagcnt;
  262. ap->variant_param_cnt = (char) vparamcnt;
  263. if(vflagcnt) {
  264. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  265. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  266. return(MEMORY_ERROR);
  267. }
  268. strcpy(ap->variant_list,varlist);
  269. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  270. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  271. return(MEMORY_ERROR);
  272. }
  273. strcpy(ap->variant_flags,varflags);
  274. }
  275. return(FINISHED);
  276. }
  277. /***************************** APPLICATION_INIT **************************/
  278. int application_init(dataptr dz)
  279. {
  280. int exit_status;
  281. int storage_cnt;
  282. int tipc, brkcnt;
  283. aplptr ap = dz->application;
  284. if(ap->vflag_cnt>0)
  285. initialise_vflags(dz);
  286. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  287. ap->total_input_param_cnt = (char)tipc;
  288. if(tipc>0) {
  289. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  290. return(exit_status);
  291. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  292. return(exit_status);
  293. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  294. return(exit_status);
  295. }
  296. brkcnt = tipc;
  297. //THERE ARE NO INPUTFILE brktables USED IN THIS PROCESS
  298. if(brkcnt>0) {
  299. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  300. return(exit_status);
  301. }
  302. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  303. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  304. return(exit_status);
  305. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  306. return(exit_status);
  307. }
  308. if((exit_status = mark_parameter_types(dz,ap))<0)
  309. return(exit_status);
  310. // establish_infile_constants() replaced by
  311. dz->infilecnt = 1;
  312. //establish_bufptrs_and_extra_buffers():
  313. return(FINISHED);
  314. }
  315. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  316. /* RWD malloc changed to calloc; helps debug version run as release! */
  317. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  318. {
  319. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  320. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  321. return(MEMORY_ERROR);
  322. }
  323. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  324. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  325. return(MEMORY_ERROR);
  326. }
  327. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  328. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  329. return(MEMORY_ERROR);
  330. }
  331. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  332. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  333. return(MEMORY_ERROR);
  334. }
  335. return(FINISHED);
  336. }
  337. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  338. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  339. {
  340. int n;
  341. for(n=0;n<storage_cnt;n++) {
  342. dz->is_int[n] = (char)0;
  343. dz->no_brk[n] = (char)0;
  344. }
  345. return(FINISHED);
  346. }
  347. /***************************** MARK_PARAMETER_TYPES **************************/
  348. int mark_parameter_types(dataptr dz,aplptr ap)
  349. {
  350. int n, m; /* PARAMS */
  351. for(n=0;n<ap->max_param_cnt;n++) {
  352. switch(ap->param_list[n]) {
  353. case('0'): break; /* dz->is_active[n] = 0 is default */
  354. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  355. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  356. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  357. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  358. default:
  359. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  360. return(PROGRAM_ERROR);
  361. }
  362. } /* OPTIONS */
  363. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  364. switch(ap->option_list[n]) {
  365. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  366. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  367. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  368. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  369. default:
  370. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  371. return(PROGRAM_ERROR);
  372. }
  373. } /* VARIANTS */
  374. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  375. switch(ap->variant_list[n]) {
  376. case('0'): break;
  377. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  378. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  379. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  380. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  381. default:
  382. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  383. return(PROGRAM_ERROR);
  384. }
  385. } /* INTERNAL */
  386. for(n=0,
  387. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  388. switch(ap->internal_param_list[n]) {
  389. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  390. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  391. case('d'): dz->no_brk[m] = (char)1; break;
  392. default:
  393. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  394. return(PROGRAM_ERROR);
  395. }
  396. }
  397. return(FINISHED);
  398. }
  399. /************************ HANDLE_THE_OUTFILE *********************/
  400. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
  401. {
  402. char *filename = (*cmdline)[0];
  403. if(filename[0]=='-' && filename[1]=='f') {
  404. dz->floatsam_output = 1;
  405. dz->true_outfile_stype = SAMP_FLOAT;
  406. filename+= 2;
  407. }
  408. if(!sloom) {
  409. if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
  410. sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
  411. return(DATA_ERROR);
  412. }
  413. }
  414. strcpy(dz->outfilename,filename);
  415. (*cmdline)++;
  416. (*cmdlinecnt)--;
  417. return(FINISHED);
  418. }
  419. /************************ OPEN_THE_OUTFILE *********************/
  420. int open_the_outfile(dataptr dz)
  421. {
  422. int exit_status;
  423. if(dz->mode == 1)
  424. dz->infile->channels = 16;
  425. else
  426. dz->infile->channels = 8;
  427. if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
  428. return(exit_status);
  429. dz->infile->channels = 1;
  430. return(FINISHED);
  431. }
  432. /***************************** ESTABLISH_APPLICATION **************************/
  433. int establish_application(dataptr dz)
  434. {
  435. aplptr ap;
  436. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  437. sprintf(errstr,"establish_application()\n");
  438. return(MEMORY_ERROR);
  439. }
  440. ap = dz->application;
  441. memset((char *)ap,0,sizeof(struct applic));
  442. return(FINISHED);
  443. }
  444. /************************* INITIALISE_VFLAGS *************************/
  445. int initialise_vflags(dataptr dz)
  446. {
  447. int n;
  448. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  449. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  450. return(MEMORY_ERROR);
  451. }
  452. for(n=0;n<dz->application->vflag_cnt;n++)
  453. dz->vflag[n] = FALSE;
  454. return FINISHED;
  455. }
  456. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  457. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  458. {
  459. int n;
  460. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  461. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  462. return(MEMORY_ERROR);
  463. }
  464. for(n=0;n<tipc;n++)
  465. ap->default_val[n] = 0.0;
  466. return(FINISHED);
  467. }
  468. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  469. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  470. {
  471. int n;
  472. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  473. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  474. return(MEMORY_ERROR);
  475. }
  476. for(n=0;n<tipc;n++)
  477. dz->is_active[n] = (char)0;
  478. return(FINISHED);
  479. }
  480. /************************* SETUP_CRUMBLE_APPLICATION *******************/
  481. int setup_crumble_application(dataptr dz)
  482. {
  483. int exit_status;
  484. aplptr ap;
  485. if((exit_status = establish_application(dz))<0) // GLOBAL
  486. return(FAILED);
  487. ap = dz->application;
  488. // SEE parstruct FOR EXPLANATION of next 2 functions
  489. if(dz->mode==0)
  490. exit_status = set_param_data(ap,0 ,12,11,"ddd0iDDDDDDi");
  491. else
  492. exit_status = set_param_data(ap,0 ,12,12,"ddddiDDDDDDi");
  493. if(exit_status<0)
  494. return(FAILED);
  495. if((exit_status = set_vflgs(ap,"",0,"","std",3,3,"dDd"))<0)
  496. return(FAILED);
  497. // set_legal_infile_structure -->
  498. dz->has_otherfile = FALSE;
  499. // assign_process_logic -->
  500. dz->input_data_type = SNDFILES_ONLY;
  501. dz->process_type = UNEQUAL_SNDFILE;
  502. dz->outfiletype = SNDFILE_OUT;
  503. return application_init(dz); //GLOBAL
  504. }
  505. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  506. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  507. {
  508. int exit_status;
  509. infileptr infile_info;
  510. if(!sloom) {
  511. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  512. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  513. return(MEMORY_ERROR);
  514. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  515. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  516. return(PROGRAM_ERROR);
  517. } else if(infile_info->filetype != SNDFILE) {
  518. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  519. return(DATA_ERROR);
  520. } else if(infile_info->channels != MONO) {
  521. sprintf(errstr,"File %s is not a mono soundfile\n",cmdline[0]);
  522. return(DATA_ERROR);
  523. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  524. sprintf(errstr,"Failed to copy file parsing information\n");
  525. return(PROGRAM_ERROR);
  526. }
  527. free(infile_info);
  528. }
  529. return(FINISHED);
  530. }
  531. /************************* SETUP_CRUMBLE_PARAM_RANGES_AND_DEFAULTS *******************/
  532. int setup_crumble_param_ranges_and_defaults(dataptr dz)
  533. {
  534. int exit_status;
  535. aplptr ap = dz->application;
  536. // set_param_ranges()
  537. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  538. // NB total_input_param_cnt is > 0 !!!
  539. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  540. return(FAILED);
  541. // get_param_ranges()
  542. ap->lo[CRSTART] = 0;
  543. ap->hi[CRSTART] = dz->duration;
  544. ap->default_val[CRSTART] = 0;
  545. ap->lo[CRSTEP1] = 0;
  546. ap->hi[CRSTEP1] = dz->duration;
  547. ap->default_val[CRSTEP1] = 0;
  548. ap->lo[CRSTEP2] = 0;
  549. ap->hi[CRSTEP2] = dz->duration;
  550. ap->default_val[CRSTEP2] = 0;
  551. if(dz->mode == 1) {
  552. ap->lo[CRSTEP3] = 0;
  553. ap->hi[CRSTEP3] = dz->duration;
  554. ap->default_val[CRSTEP3] = 0;
  555. }
  556. ap->lo[CRORIENT] = 1;
  557. if(dz->mode == 1)
  558. ap->hi[CRORIENT] = 16;
  559. else
  560. ap->hi[CRORIENT] = 8;
  561. ap->default_val[CRORIENT] = 1;
  562. ap->lo[CRSIZE] = 10.00001 * MS_TO_SECS;
  563. ap->hi[CRSIZE] = dz->duration;
  564. ap->default_val[CRSIZE] = min(.25,dz->duration/2.0);
  565. ap->lo[CRRAND] = 0;
  566. ap->hi[CRRAND] = 1;
  567. ap->default_val[CRRAND] = 0;
  568. ap->lo[CRISCAT] = 0;
  569. ap->hi[CRISCAT] = 1;
  570. ap->default_val[CRISCAT] = 0;
  571. ap->lo[CROSCAT] = 0;
  572. ap->hi[CROSCAT] = 1;
  573. ap->default_val[CROSCAT] = 0;
  574. ap->lo[CROSTR] = 1;
  575. ap->hi[CROSTR] = 64;
  576. ap->default_val[CROSTR] = 1;
  577. ap->lo[CRPSCAT] = 0;
  578. ap->hi[CRPSCAT] = 12;
  579. ap->default_val[CRPSCAT] = 0;
  580. ap->lo[CRSEED] = 1;
  581. ap->hi[CRSEED] = 256;
  582. ap->default_val[CRSEED] = 1;
  583. ap->lo[CRSPLICE] = 2;
  584. ap->hi[CRSPLICE] = 50;
  585. ap->default_val[CRSPLICE] = 5;
  586. ap->lo[CRTAIL] = 0;
  587. ap->hi[CRTAIL] = 1000;
  588. ap->default_val[CRTAIL] = 0;
  589. ap->lo[CRDUR] = 0;
  590. ap->hi[CRDUR] = 3600;
  591. ap->default_val[CRDUR] = 0;
  592. dz->maxmode = 2;
  593. if(!sloom)
  594. put_default_vals_in_all_params(dz);
  595. return(FINISHED);
  596. }
  597. /********************************* PARSE_SLOOM_DATA *********************************/
  598. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  599. {
  600. int exit_status;
  601. int cnt = 1, infilecnt;
  602. int filesize, insams, inbrksize;
  603. double dummy;
  604. int true_cnt = 0;
  605. // aplptr ap;
  606. while(cnt<=PRE_CMDLINE_DATACNT) {
  607. if(cnt > argc) {
  608. sprintf(errstr,"Insufficient data sent from TK\n");
  609. return(DATA_ERROR);
  610. }
  611. switch(cnt) {
  612. case(1):
  613. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  614. sprintf(errstr,"Cannot read process no. sent from TK\n");
  615. return(DATA_ERROR);
  616. }
  617. break;
  618. case(2):
  619. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  620. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  621. return(DATA_ERROR);
  622. }
  623. if(dz->mode > 0)
  624. dz->mode--;
  625. //setup_particular_application() =
  626. if((exit_status = setup_crumble_application(dz))<0)
  627. return(exit_status);
  628. // ap = dz->application;
  629. break;
  630. case(3):
  631. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  632. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  633. return(DATA_ERROR);
  634. }
  635. if(infilecnt < 1) {
  636. true_cnt = cnt + 1;
  637. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  638. }
  639. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  640. return(exit_status);
  641. break;
  642. case(INPUT_FILETYPE+4):
  643. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  644. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  645. return(DATA_ERROR);
  646. }
  647. break;
  648. case(INPUT_FILESIZE+4):
  649. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  650. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  651. return(DATA_ERROR);
  652. }
  653. dz->insams[0] = filesize;
  654. break;
  655. case(INPUT_INSAMS+4):
  656. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  657. sprintf(errstr,"Cannot read insams sent from TK\n");
  658. return(DATA_ERROR);
  659. }
  660. dz->insams[0] = insams;
  661. break;
  662. case(INPUT_SRATE+4):
  663. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  664. sprintf(errstr,"Cannot read srate sent from TK\n");
  665. return(DATA_ERROR);
  666. }
  667. break;
  668. case(INPUT_CHANNELS+4):
  669. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  670. sprintf(errstr,"Cannot read channels sent from TK\n");
  671. return(DATA_ERROR);
  672. }
  673. break;
  674. case(INPUT_STYPE+4):
  675. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  676. sprintf(errstr,"Cannot read stype sent from TK\n");
  677. return(DATA_ERROR);
  678. }
  679. break;
  680. case(INPUT_ORIGSTYPE+4):
  681. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  682. sprintf(errstr,"Cannot read origstype sent from TK\n");
  683. return(DATA_ERROR);
  684. }
  685. break;
  686. case(INPUT_ORIGRATE+4):
  687. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  688. sprintf(errstr,"Cannot read origrate sent from TK\n");
  689. return(DATA_ERROR);
  690. }
  691. break;
  692. case(INPUT_MLEN+4):
  693. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  694. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  695. return(DATA_ERROR);
  696. }
  697. break;
  698. case(INPUT_DFAC+4):
  699. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  700. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  701. return(DATA_ERROR);
  702. }
  703. break;
  704. case(INPUT_ORIGCHANS+4):
  705. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  706. sprintf(errstr,"Cannot read origchans sent from TK\n");
  707. return(DATA_ERROR);
  708. }
  709. break;
  710. case(INPUT_SPECENVCNT+4):
  711. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  712. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  713. return(DATA_ERROR);
  714. }
  715. dz->specenvcnt = dz->infile->specenvcnt;
  716. break;
  717. case(INPUT_WANTED+4):
  718. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  719. sprintf(errstr,"Cannot read wanted sent from TK\n");
  720. return(DATA_ERROR);
  721. }
  722. break;
  723. case(INPUT_WLENGTH+4):
  724. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  725. sprintf(errstr,"Cannot read wlength sent from TK\n");
  726. return(DATA_ERROR);
  727. }
  728. break;
  729. case(INPUT_OUT_CHANS+4):
  730. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  731. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  732. return(DATA_ERROR);
  733. }
  734. break;
  735. /* RWD these changes to samps - tk will have to deal with that! */
  736. case(INPUT_DESCRIPTOR_BYTES+4):
  737. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  738. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  739. return(DATA_ERROR);
  740. }
  741. break;
  742. case(INPUT_IS_TRANSPOS+4):
  743. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  744. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  745. return(DATA_ERROR);
  746. }
  747. break;
  748. case(INPUT_COULD_BE_TRANSPOS+4):
  749. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  750. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  751. return(DATA_ERROR);
  752. }
  753. break;
  754. case(INPUT_COULD_BE_PITCH+4):
  755. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  756. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  757. return(DATA_ERROR);
  758. }
  759. break;
  760. case(INPUT_DIFFERENT_SRATES+4):
  761. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  762. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  763. return(DATA_ERROR);
  764. }
  765. break;
  766. case(INPUT_DUPLICATE_SNDS+4):
  767. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  768. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  769. return(DATA_ERROR);
  770. }
  771. break;
  772. case(INPUT_BRKSIZE+4):
  773. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  774. sprintf(errstr,"Cannot read brksize sent from TK\n");
  775. return(DATA_ERROR);
  776. }
  777. if(inbrksize > 0) {
  778. switch(dz->input_data_type) {
  779. case(WORDLIST_ONLY):
  780. break;
  781. case(PITCH_AND_PITCH):
  782. case(PITCH_AND_TRANSPOS):
  783. case(TRANSPOS_AND_TRANSPOS):
  784. dz->tempsize = inbrksize;
  785. break;
  786. case(BRKFILES_ONLY):
  787. case(UNRANGED_BRKFILE_ONLY):
  788. case(DB_BRKFILES_ONLY):
  789. case(ALL_FILES):
  790. case(ANY_NUMBER_OF_ANY_FILES):
  791. if(dz->extrabrkno < 0) {
  792. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  793. return(DATA_ERROR);
  794. }
  795. if(dz->brksize == NULL) {
  796. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  797. return(PROGRAM_ERROR);
  798. }
  799. dz->brksize[dz->extrabrkno] = inbrksize;
  800. break;
  801. default:
  802. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  803. dz->input_data_type);
  804. return(PROGRAM_ERROR);
  805. }
  806. break;
  807. }
  808. break;
  809. case(INPUT_NUMSIZE+4):
  810. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  811. sprintf(errstr,"Cannot read numsize sent from TK\n");
  812. return(DATA_ERROR);
  813. }
  814. break;
  815. case(INPUT_LINECNT+4):
  816. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  817. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  818. return(DATA_ERROR);
  819. }
  820. break;
  821. case(INPUT_ALL_WORDS+4):
  822. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  823. sprintf(errstr,"Cannot read all_words sent from TK\n");
  824. return(DATA_ERROR);
  825. }
  826. break;
  827. case(INPUT_ARATE+4):
  828. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  829. sprintf(errstr,"Cannot read arate sent from TK\n");
  830. return(DATA_ERROR);
  831. }
  832. break;
  833. case(INPUT_FRAMETIME+4):
  834. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  835. sprintf(errstr,"Cannot read frametime sent from TK\n");
  836. return(DATA_ERROR);
  837. }
  838. dz->frametime = (float)dummy;
  839. break;
  840. case(INPUT_WINDOW_SIZE+4):
  841. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  842. sprintf(errstr,"Cannot read window_size sent from TK\n");
  843. return(DATA_ERROR);
  844. }
  845. break;
  846. case(INPUT_NYQUIST+4):
  847. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  848. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  849. return(DATA_ERROR);
  850. }
  851. break;
  852. case(INPUT_DURATION+4):
  853. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  854. sprintf(errstr,"Cannot read duration sent from TK\n");
  855. return(DATA_ERROR);
  856. }
  857. break;
  858. case(INPUT_MINBRK+4):
  859. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  860. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  861. return(DATA_ERROR);
  862. }
  863. break;
  864. case(INPUT_MAXBRK+4):
  865. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  866. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  867. return(DATA_ERROR);
  868. }
  869. break;
  870. case(INPUT_MINNUM+4):
  871. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  872. sprintf(errstr,"Cannot read minnum sent from TK\n");
  873. return(DATA_ERROR);
  874. }
  875. break;
  876. case(INPUT_MAXNUM+4):
  877. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  878. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  879. return(DATA_ERROR);
  880. }
  881. break;
  882. default:
  883. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  884. return(PROGRAM_ERROR);
  885. }
  886. cnt++;
  887. }
  888. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  889. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  890. return(DATA_ERROR);
  891. }
  892. if(true_cnt)
  893. cnt = true_cnt;
  894. *cmdlinecnt = 0;
  895. while(cnt < argc) {
  896. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  897. return(exit_status);
  898. cnt++;
  899. }
  900. return(FINISHED);
  901. }
  902. /********************************* GET_TK_CMDLINE_WORD *********************************/
  903. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  904. {
  905. if(*cmdlinecnt==0) {
  906. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  907. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  908. return(MEMORY_ERROR);
  909. }
  910. } else {
  911. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  912. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  913. return(MEMORY_ERROR);
  914. }
  915. }
  916. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  917. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  918. return(MEMORY_ERROR);
  919. }
  920. strcpy((*cmdline)[*cmdlinecnt],q);
  921. (*cmdlinecnt)++;
  922. return(FINISHED);
  923. }
  924. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  925. int assign_file_data_storage(int infilecnt,dataptr dz)
  926. {
  927. int exit_status;
  928. int no_sndfile_system_files = FALSE;
  929. dz->infilecnt = infilecnt;
  930. if((exit_status = allocate_filespace(dz))<0)
  931. return(exit_status);
  932. if(no_sndfile_system_files)
  933. dz->infilecnt = 0;
  934. return(FINISHED);
  935. }
  936. /************************* redundant functions: to ensure libs compile OK *******************/
  937. int assign_process_logic(dataptr dz)
  938. {
  939. return(FINISHED);
  940. }
  941. void set_legal_infile_structure(dataptr dz)
  942. {}
  943. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  944. {
  945. return(FINISHED);
  946. }
  947. int setup_internal_arrays_and_array_pointers(dataptr dz)
  948. {
  949. return(FINISHED);
  950. }
  951. int establish_bufptrs_and_extra_buffers(dataptr dz)
  952. {
  953. return(FINISHED);
  954. }
  955. int read_special_data(char *str,dataptr dz)
  956. {
  957. return(FINISHED);
  958. }
  959. int inner_loop
  960. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  961. {
  962. return(FINISHED);
  963. }
  964. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  965. {
  966. return(FINISHED);
  967. }
  968. /******************************** USAGE1 ********************************/
  969. int usage1(void)
  970. {
  971. usage2("sound");
  972. return(USAGE_ONLY);
  973. }
  974. /********************************************************************************************/
  975. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  976. {
  977. if(!strcmp(prog_identifier_from_cmdline,"sound")) dz->process = CRUMBLE;
  978. else {
  979. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  980. return(USAGE_ONLY);
  981. }
  982. return(FINISHED);
  983. }
  984. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  985. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  986. {
  987. int n;
  988. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  989. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  990. return(MEMORY_ERROR);
  991. }
  992. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  993. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  994. return(MEMORY_ERROR);
  995. }
  996. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  997. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  998. return(MEMORY_ERROR);
  999. }
  1000. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1001. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  1002. return(MEMORY_ERROR);
  1003. }
  1004. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1005. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  1006. return(MEMORY_ERROR);
  1007. }
  1008. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1009. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  1010. return(MEMORY_ERROR);
  1011. }
  1012. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1013. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  1014. return(MEMORY_ERROR);
  1015. }
  1016. for(n=0;n<brkcnt;n++) {
  1017. dz->brk[n] = NULL;
  1018. dz->brkptr[n] = NULL;
  1019. dz->brkinit[n] = 0;
  1020. dz->brksize[n] = 0;
  1021. }
  1022. return(FINISHED);
  1023. }
  1024. /******************************** USAGE2 ********************************/
  1025. int usage2(char *str)
  1026. {
  1027. if(!strcmp(str,"sound")) {
  1028. fprintf(stdout,
  1029. "USAGE: crumble sound 1 inf outf stt dur1 dur2 params\n"
  1030. "OR: crumble sound 2 inf outf stt dur1 dur2 dur3 params\n"
  1031. "\n"
  1032. "where PARAMS are\n"
  1033. "orient size rand iscat oscat ostrch pscat seed [-ssplice] [-ttail]\n"
  1034. "\n"
  1035. "Project a MONO source on all channels of multichan output, then segment it,\n"
  1036. "and distribute the segments over smaller and smaller groups of channels.\n"
  1037. "\n"
  1038. "Mode 1 gives 8-channel output (ochans = 8)\n"
  1039. "Mode 2 gives 16-channel output (ochans = 16)\n"
  1040. "\n"
  1041. "STT Start time of crumbling.\n"
  1042. "DUR1 Duration of section where signal split into 2 images.\n"
  1043. "DUR2 Duration of section where signal split into 4 images.\n"
  1044. "DUR3 (Mode 2) Duration of section where signal split into 8 images.\n"
  1045. "ORIENT Input image first splits onto 2 blocks each of ochans/2 adjacent chans.\n"
  1046. " (1) chan \"ori\" with adjacent clockwise channels,\n"
  1047. " (2) remaining channels.\n"
  1048. "SIZE* (Average) duration of cut segments.\n"
  1049. "RAND* Randomisation of segment size. (Range 0 - 1)\n"
  1050. " Max(1) modifies \"siz\" randomly between siz/2 and (3*siz)/2\n"
  1051. "ISCAT* Scattering (in source) of start-time of next segment cut. (Range 0 - 1)\n"
  1052. " Cut-time in source always advances.\n"
  1053. " With no scatter, step to next cut-time = length of previous segment cut.\n"
  1054. " With max \"isct\"(1) step by random time between 0 and previous-seglen.\n"
  1055. "OSCAT* Scattering (in output) of time-placement of segment used.(Range 0 - 1)\n"
  1056. " Time in output always advances.\n"
  1057. " With no scatter, step to next output-time = length of last segment cut.\n"
  1058. " With max \"osct\"(1) step by random time between >0 and previous-seglen.\n"
  1059. "OSTRCH* Stretching of time-placement in output. (Range 1 - 64)\n"
  1060. " Step to next sgement-placement in output, is multiplied by ostr.\n"
  1061. " ostr > 1 should generate silent gaps in the output.\n"
  1062. "PSCAT* Pitch variation of output segments (Semitones).\n"
  1063. " for e.g. psct=3, pitch varies at random between +3 and -3 semitones.\n"
  1064. "SEED Same seed value gives identical output on successive process runs.\n"
  1065. "SPLICE Length of splices which cut the segments (in millseconds).\n"
  1066. "TAIL* Length of any exponential tail on segments (in millseconds).\n"
  1067. "\n"
  1068. "Parameters marked with \"*\" can vary over time (i.e. time in the outfile).\n"
  1069. "\n");
  1070. } else
  1071. fprintf(stdout,"Unknown option '%s'\n",str);
  1072. return(USAGE_ONLY);
  1073. }
  1074. int usage3(char *str1,char *str2)
  1075. {
  1076. fprintf(stderr,"Insufficient parameters on command line.\n");
  1077. return(USAGE_ONLY);
  1078. }
  1079. /******************************** CRUMBLE ********************************
  1080. *
  1081. * For an 8-channel output...
  1082. * The process starts copying the mono input to ALL channels of the multichan output.
  1083. * At time-boundary[0] = "monoreadend", it begins to send segments of the input to channels 1234 and 5678 alternately
  1084. * (could be 2345 6781 etc. depending on the aprameter "orient").
  1085. * At time-boundary[1], begins to send segments of the input to channels 12 34 56 and 78 randomly permuted
  1086. * (could be 23 45 67 81 etc. depending on the parameter "orient").
  1087. * At time-boundary[2], begins to send segments of the input to channels 1 2 3 4 5 6 7 and 8 randomly permuted
  1088. *
  1089. * If the segments have no tails (CRTAIL = 0), they are cut using a "splicelen" splice at both ends.
  1090. * With no input scatter (CRISCAT), segments are cut from the source in time order, with no gaps or overlaps.
  1091. * With scatter, start of next segment may (randomly) begin within the previous segment.
  1092. *
  1093. * With no output scatter (CROSCAT), segments are joined to the output in time order, with no gaps or overlaps.
  1094. * With scatter, start of next segment may begin (randomly) within the previous segment (<1)
  1095. * or (randomly) beyond the end of the previous segment (>1).
  1096. *
  1097. * After being cut, the segments may be (randomly) transposed within a speicified range (CRPSCAT).
  1098. *
  1099. * If the segments have tails (CRTAIL > 0), segments calculations are done AS IF the segments had no tails
  1100. * (cutting time within source and placement time in output are calculated exactly as above
  1101. * using the length of the segments BEFORE the tail is added, in all calculations).
  1102. *
  1103. * When the segments are cut, however, extra samples are added to the end of the bare seglength
  1104. * and in the output, an exponential decay is applied over these tails.
  1105. *
  1106. * If tails are specified, the initial (unsegmented) section is also given a tail.
  1107. * This means that, initially "monoreadend" must be set at the END of the tail, so the mono->multimono process
  1108. * continues to the end of the tail.
  1109. * The read_process must then baktrak to the start of the tail, but it will then be BEFORE the "monoreadend" marker.
  1110. * to ensure that that this does not trap the process in looping in the mono->multimono process,
  1111. * the "monoreadend" is reset to ZERO, so the process knows it must not continue with mono->multimono processing.
  1112. */
  1113. int crumble(dataptr dz)
  1114. {
  1115. int exit_status, ochancnt, passno, chan, ochan, startchan, thischan, reread, sector, lastsector, n, m, firstread, monoread_completed;
  1116. int curtailed, permsize, permcnt = 0, gpsize = 0, thisperm, lastperm, lastperm2, **perm;
  1117. int obuflen, segsamps, segend, oseglen, instep, outstep, lo, hi, crstartsamps, thistail;
  1118. int write_end = 0, segstart_opos, opos, ipos, epos, eposend, samples_before_bufstart;
  1119. float *ibuf = dz->sampbuf[0], *iovbuf = dz->sampbuf[1], *obuf = dz->sampbuf[2], *oovbuf = dz->sampbuf[3], *ebuf = dz->sampbuf[4];
  1120. double time, pshift, incr, frac, diff, val, iposd, boundary[4], balance[5];
  1121. double maxsamp, normaliser = 1.0, srate = (double)dz->infile->srate, rval, spliceval, crsize, crstart;
  1122. int samptime, endsplicstart, monoreadend, orig_monoreadend, splicetime, endsplice, buffer_end;
  1123. crstart = dz->param[CRSTART]; // Start of segmentation process (end of monoread section)
  1124. crstartsamps = (int)ceil(crstart * srate); // Start of segmentation process
  1125. if(dz->mode == 1)
  1126. ochancnt = 16;
  1127. else
  1128. ochancnt = 8;
  1129. obuflen = dz->buflen * ochancnt;
  1130. if((perm = (int **)malloc(17 * sizeof(int *)))==NULL) { // Establish the arrays to permute channel and channel-group order
  1131. sprintf(errstr,"Insufficient memory for random permutation arrays.\n");
  1132. return(MEMORY_ERROR);
  1133. }
  1134. permsize = 2; // sets up perm[2], perm[4], perm[8] (perm[16]) containing 2,4,8,(16) integer entries to perm
  1135. while(permsize < 17) { // (perm[2] is redundant, but it simplifies later coding to create it here)
  1136. if((perm[permsize] = (int *)malloc(permsize * sizeof(int)))==NULL) {
  1137. sprintf(errstr,"Insufficient memory for random-permutation-array[%d].\n",permsize);
  1138. return(MEMORY_ERROR);
  1139. }
  1140. permsize *= 2;
  1141. }
  1142. boundary[0] = crstart; // End of copying mono to all of outchannels
  1143. boundary[1] = boundary[0] + dz->param[CRSTEP1]; // End of routing to (ochancnt/2)-size channel-groupings
  1144. boundary[2] = boundary[1] + dz->param[CRSTEP2]; // End of routing to (ochancnt/4)-size channel-groupings
  1145. balance[1] = ROOT_2;
  1146. balance[2] = balance[1] * ROOT_2; // As output divided amongst more channels,
  1147. balance[3] = balance[2] * ROOT_2; // individual channel level increases by ROOT2
  1148. if(dz->mode==0)
  1149. lastsector = 3; // In last sector, output routed to individual channels
  1150. else {
  1151. boundary[3] = boundary[2] + dz->param[CRSTEP3];
  1152. balance[4] = balance[3] * ROOT_2;
  1153. lastsector = 4;
  1154. }
  1155. // CHECK FOR TAIL ON END OF "MONOREAD" SECTION
  1156. for(passno = 0;passno < 2;passno++) {
  1157. srand((int)dz->param[CRSEED]); // Reset random seed, so levels in real output pass match levels in level-check pass.
  1158. permsize = 2; // For the chan-group (or channel) permutations that will be acative (2,4,8,(16))
  1159. while(permsize < 17) { // Establish initial permutation of order for each active grouping
  1160. lastperm = -1; // For more details, see 2nd call to "doperm" below, and the notes with "doperm" function
  1161. lastperm2 = -1;
  1162. for(n=0;n<permsize;n++)
  1163. perm[permsize][n] = n; // Do initial random permute of entries for 2-perm (others are done later)
  1164. if(n==2)
  1165. doperm(perm[permsize],permsize,&lastperm,&lastperm2);
  1166. permsize *= 2;
  1167. }
  1168. if(passno == 0)
  1169. fprintf(stdout,"INFO: Assessing output level.\n");
  1170. else
  1171. fprintf(stdout,"INFO: Generating output.\n");
  1172. // RESET ALL PASS VARIABLE
  1173. if(passno == 1) {
  1174. if((sndseekEx(dz->ifd[0],0,0) < 0)){
  1175. sprintf(errstr,"sndseek failed in input file.\n");
  1176. return SYSTEM_ERROR;
  1177. }
  1178. }
  1179. if(dz->notailanywhere)
  1180. dz->hastail = 0;
  1181. else { // If the segments have tails
  1182. if(dz->brksize[CRTAIL]) { // Find the tail length at the end of the monoread section
  1183. if((exit_status = read_value_from_brktable(dz->param[CRSTART],CRTAIL,dz))<0)
  1184. return exit_status;
  1185. }
  1186. if(flteq(dz->param[CRTAIL],0.0))
  1187. dz->hastail = 0;
  1188. else
  1189. dz->hastail = 1;
  1190. }
  1191. if(dz->hastail) { // If segment has tail at end of monoread section
  1192. dz->param[CRTAIL] *= MS_TO_SECS; // Read the tail-length, and ensure it is at-least minimum length
  1193. dz->param[CRTAIL] = max(dz->param[CRTAIL],dz->param[CRSPLICE] * 2);
  1194. dz->iparam[CRTAIL] = (int)ceil(dz->param[CRTAIL] * srate);
  1195. endsplicstart = (int)ceil(crstart * srate); // start-of-endsplice is AT END of monoread-segment
  1196. orig_monoreadend = endsplicstart + dz->iparam[CRTAIL]; // and we initially READ to end of the tail
  1197. } else { // If there is NO TAIL at end of monoread-segment
  1198. orig_monoreadend = (int)round(crstart * srate); // We initially READ to end of the segment.
  1199. endsplicstart = orig_monoreadend - dz->iparam[CRSPLICE];// and start-of-endsplice is just BEFORE end of monoread-segment.
  1200. }
  1201. monoreadend = orig_monoreadend;
  1202. dz->samps_left = dz->insams[0];
  1203. dz->total_samps_read = 0;
  1204. samples_before_bufstart = 0;
  1205. dz->total_samps_written = 0;
  1206. write_end = 0;
  1207. sector = 0;
  1208. ipos = 0;
  1209. opos = 0;
  1210. time = 0.0;
  1211. splicetime = -endsplicstart; // splice time gets to 0 at start of splice
  1212. samptime = 0;
  1213. maxsamp = 0.0;
  1214. thisperm = perm[2][0];
  1215. firstread = 1;
  1216. lastperm = -1;
  1217. lastperm2 = -1;
  1218. monoread_completed = 0;
  1219. curtailed = 0;
  1220. memset((char *)ibuf,0,dz->buflen * 2 * sizeof(float)); // Zero the input buf and input-overflow buf
  1221. memset((char *)obuf,0,obuflen * 2 * sizeof(float)); // Zero the output buf and output-overflow buf
  1222. while(dz->samps_left > 0) {
  1223. if(firstread) {
  1224. ibuf = dz->sampbuf[0]; // On first read, fill the buffer AND the read-ahead buffer
  1225. dz->buflen *= 2;
  1226. if((exit_status = read_samps(ibuf,dz))<0)
  1227. return(exit_status);
  1228. dz->buflen /= 2; // After initial read, restore true length of buffer
  1229. firstread = 0;
  1230. } else {
  1231. ibuf = dz->sampbuf[1]; // On subsequent reads, read into the read_ahead
  1232. if((exit_status = read_samps(ibuf,dz))<0)
  1233. return(exit_status);
  1234. ibuf = dz->sampbuf[0]; // but write will be from input-buffer proper
  1235. }
  1236. reread = 0;
  1237. // BEFORE CRUMBLE STARTS, JUST COPY INPUT TO (MULTICHAN) OUTPUT, "MONOREAD"
  1238. // No need to read brktables here as we already have length of tail,
  1239. // and all other possible timevarying params concern segmentation.
  1240. while(samptime < monoreadend) {
  1241. if(splicetime > 0) { // If in end splice (or exponential tail)
  1242. if(dz->hastail) {
  1243. val = (double)(dz->iparam[CRTAIL] - splicetime)/(double)dz->iparam[CRTAIL];
  1244. val *= val; // do exponential decay of tail
  1245. } else
  1246. val = (double)(dz->iparam[CRSPLICE] - splicetime)/(double)dz->iparam[CRSPLICE];
  1247. val *= ibuf[ipos]; // or do normal splice
  1248. } else
  1249. val = ibuf[ipos]; // otherwise do straight copy
  1250. for(chan = 0; chan < ochancnt; chan++)
  1251. obuf[opos++] = (float)val; // Mono to multimono output
  1252. ipos++;
  1253. if(opos >= obuflen) { // If output buffer full
  1254. if(passno == 0) {
  1255. for(n=0;n<obuflen;n++)
  1256. maxsamp = max(maxsamp,fabs(obuf[n])); // On initial pass, find maxsamp
  1257. dz->process = BRASSAGE; // (Force correct progress-bar display on Loom, based on samples READ)
  1258. display_virtual_time(dz->total_samps_read,dz);
  1259. dz->total_samps_written += obuflen;
  1260. dz->process = CRUMBLE;
  1261. } else { // On write-data pass,
  1262. if(normaliser < 1.0) { // Do any required normalisation
  1263. for(n=0;n<obuflen;n++)
  1264. obuf[n] = (float)(obuf[n] * normaliser);
  1265. }
  1266. dz->process = BRASSAGE; // and write to output
  1267. if((exit_status = write_samps(obuf,obuflen,dz))<0)
  1268. return(exit_status);
  1269. dz->process = CRUMBLE;
  1270. }
  1271. memset((char *)obuf,0,obuflen * sizeof(float)); // Zero the output buf (there is no overflow at this stage)
  1272. opos -= obuflen; // Reset output buffer pointer
  1273. }
  1274. samptime++;
  1275. splicetime++;
  1276. if(ipos >= dz->buflen) {
  1277. reread = 1; // Whilst merely reading the input to the output
  1278. ipos = 0; // reset inbuf pointer to 0, and set flag to go read more samples.
  1279. break;
  1280. }
  1281. }
  1282. if(reread) { // Until "starttime" is reached, continue monoread
  1283. memcpy((char *)ibuf,(char *)iovbuf,dz->buflen * sizeof(float)); // Copy the read-ahead buffer back into ibuf
  1284. memset((char *)iovbuf,0,dz->buflen * sizeof(float)); // Zero the read-ahead buf
  1285. samples_before_bufstart += dz->buflen; // Update count of samples read before buffer-start (used to calculate "time")
  1286. continue;
  1287. } else
  1288. monoread_completed++;
  1289. // AT END OF MONO->MULTIMONO READ
  1290. // IF THE MULTIMONO HAS A TAIL, RECONFIGURE THE READ INFORMATION
  1291. if(monoread_completed == 1) {
  1292. if(dz->hastail) { // Seek (back) to start of tail
  1293. if((sndseekEx(dz->ifd[0],crstartsamps,0) < 0)){
  1294. sprintf(errstr,"sndseek (back to start of segmentation) failed in input file.\n");
  1295. return SYSTEM_ERROR;
  1296. }
  1297. ibuf = dz->sampbuf[0]; // Read a fresh DOUBLE buffer
  1298. dz->buflen *= 2; // (first zeroing the input & input-overflow bufs).
  1299. memset((char *)ibuf,0,dz->buflen * sizeof(float));
  1300. if((exit_status = read_samps(ibuf,dz))<0)
  1301. return(exit_status);
  1302. dz->buflen /= 2; // Reset for subsequent reads to be single bufreads
  1303. // NB Subsequent reads will be to the READ-AHEAD buffer sampbuf[1], but this is set/unset at top of read loop
  1304. samples_before_bufstart = crstartsamps; // Reset the input read counters.
  1305. time = (double)samples_before_bufstart/srate;
  1306. if(dz->iparam[CRDUR] > 0 && crstartsamps >= dz->iparam[CRDUR]) {
  1307. curtailed = 1;
  1308. break;
  1309. }
  1310. dz->total_samps_read = samples_before_bufstart + dz->ssampsread;
  1311. dz->samps_left = dz->insams[0] - dz->total_samps_read;
  1312. ipos = 0; // Reposition the input buffer pointer.
  1313. opos = crstartsamps * ochancnt;
  1314. opos -= dz->total_samps_written;
  1315. if(opos < 0) { // Should be rendant if buffer-szie calculations are correct!!!
  1316. sprintf(errstr,"OBUF UNDERFLOW\n");
  1317. return PROGRAM_ERROR;
  1318. }
  1319. monoreadend = -1; // Ensure we're not trapped forever in monoreadings.
  1320. // OTHERWISE, SET THE TIME TO END OF MONOREAD
  1321. } else
  1322. time = dz->param[CRSTART];
  1323. }
  1324. // sampsread could be a less-than-full SINGLE buffer: exit loop once samples exhausted
  1325. buffer_end = min(dz->ssampsread,dz->buflen);// or a full DOUBLE buffer (read-ahead): exit loop once pointer falls beyond SINGLE buffer
  1326. write_end = opos; // Latest sample written to output buffer is at opos
  1327. // ONLY ON CROSSING SECTOR BOUNDARIES, AND ONLY BEFORE WE REACH THE LASTSECTOR
  1328. // Crossing a sector boundary halves the channel-grouping in the output.
  1329. // For an 8-chan output
  1330. // Initial output is to 01234567: crossing 1st boundary puts output on 0123 & 4567
  1331. // (these groupings may be offset, by "orient", but each still has 4 adjacent chans).
  1332. // Hence we permute 2 sets of 4chans
  1333. // Crossing 2nd boundary puts output on 01 & 23 & 45 & 67 (possibly offset etc)
  1334. // Hence we permute 4 sets of 2chans
  1335. // Crossing 3rd boundary puts output on 0 & 1 & 2 & 3 & 4 & 5 & 6 & 7
  1336. // Hence we permute 8 individual channels
  1337. // END OF SECTOR BOUNDARY CALCULATIONS
  1338. // READING AND WRITING CUT SEGMENTS
  1339. while(ipos < buffer_end) {
  1340. if(sector < lastsector) { // Until completely fragmented to separate chans
  1341. if(time >= boundary[sector]) { // Check if we've crossed time-boundary of next sector
  1342. sector++; // Set up params to perm the groups-of-chans OR (in last sector) individual channels.
  1343. permsize = (int)pow(2,sector); // Sector 1 has 2 groups of (4)chans, sector 2 has 4 groups of (2)chans etc.
  1344. gpsize = ochancnt/permsize; // no of channels in each group.
  1345. // Modify how the perm works, as number of perm items increases ....
  1346. lastperm = thisperm * 2; // e.g. with gpsize 4, if lastperm=1 last-used chan-gp-of4 contained channels 4567 (possibly offset etc).
  1347. lastperm2 = lastperm + 1; // After halving gpsize to 2, lastperm new gets "2" (chans 45) and lastperm2 gets "3" (chans 67).
  1348. // e.g. with gpsize 2, if lastperm = 1 last-used chan-gp-of-2 contained channel 23.
  1349. // after halving gpsize to 1, lastperm gets "2" (chan 2) and lastperm2 gets "3" (chans 3).
  1350. // This ensures, that the new (larger) perm avoids using-first the channels used-last in previous-perm.
  1351. // See the function "doperm" for more detials of how this works.
  1352. if(permsize==2) // Where there are only 2 groups,
  1353. permcnt = !permcnt; // alternate between groups (0 and 1)
  1354. else // otherwise perm the order of the groups, or the individual chans.
  1355. doperm(perm[permsize],permsize,&lastperm,&lastperm2);
  1356. permcnt = 0; // Initialise the count of perm-items used.
  1357. }
  1358. }
  1359. if((exit_status= read_values_from_all_existing_brktables(time,dz))< 0)
  1360. return exit_status;
  1361. // Find size of tail, if any
  1362. if(!dz->notailanywhere) {
  1363. if(dz->brksize[CRTAIL]) {
  1364. if(dz->param[CRTAIL] == 0.0)
  1365. dz->hastail = 0;
  1366. else {
  1367. dz->hastail = 1;
  1368. dz->param[CRTAIL] = max((dz->application->lo[CRSPLICE] * 2),dz->param[CRTAIL]);
  1369. dz->param[CRTAIL] *= MS_TO_SECS;
  1370. dz->iparam[CRTAIL] = (int)ceil(dz->param[CRTAIL] * srate);
  1371. }
  1372. }
  1373. }
  1374. // Find size of segment to cut, and initial values of subsequent step in infile and outfile
  1375. crsize = dz->param[CRSIZE];
  1376. if(dz->param[CRRAND] > 0.0) {
  1377. rval = drand48() * 0.5; // Range -1/2 to +1/2
  1378. rval *= dz->param[CRRAND]; // Maxrange -1/2 to +1/2
  1379. rval += 1.0; // Maxrange 1/2 to 3/2
  1380. crsize *= rval;
  1381. }
  1382. segsamps = (int)round(crsize * srate); // samps to read
  1383. instep = segsamps; // step to next sample to read (before any randomisation)
  1384. outstep = segsamps; // step (in gp-samples) to next sample to write (before any randomisation)
  1385. // Find transposition (and corresponding read-incr) of segment
  1386. pshift = ((drand48() * 2.0) - 1.0) * dz->param[CRPSCAT];// Randomly scatter pitch-shift (+- pshift range)
  1387. incr = pow(2.0,-pshift/SEMITONES_PER_OCTAVE); // If transpos is +ve, pow(2,-ve) < 1 : if transpos is -ve, pos(2,+ve) is > 1
  1388. if(dz->hastail) {
  1389. thistail = dz->iparam[CRTAIL];
  1390. if(pshift != 0.0) // If transposing down (incr +ve) output is inter, so tail would be lengthened
  1391. thistail = (int)round((double)thistail/incr); // To retain tail of same length, read LESS input samples, to make tail correct length
  1392. segsamps += thistail; // Increase the number of input samples to read, to include tail samples
  1393. }
  1394. // Write (transposed) input segment into enveloping buffer, and note its length
  1395. iposd = ipos;
  1396. epos = 0;
  1397. segend = ipos + segsamps;
  1398. while(iposd < segend) {
  1399. lo = (int)floor(iposd);
  1400. frac = iposd - (double)lo;
  1401. hi = lo + 1;
  1402. diff = ibuf[hi] - ibuf[lo];
  1403. val = ibuf[lo] + (diff * frac);
  1404. ebuf[epos++] = (float)val;
  1405. iposd += incr;
  1406. }
  1407. oseglen = epos;
  1408. eposend = oseglen-1;
  1409. if(dz->warned && dz->hastail) { // IF notailanywhere, value of CRTAIL has been preset to CRSPLICE
  1410. if(oseglen <= dz->iparam[CRSPLICE] + dz->iparam[CRTAIL]) {
  1411. if(dz->notailanywhere)
  1412. sprintf(errstr,"SEGMENT TOO SHORT FOR SPLICES.\n");
  1413. else
  1414. sprintf(errstr,"SEGMENT (%lf) TOO SHORT FOR SPLICE AND TAIL (%lf)\n",
  1415. (double)oseglen/srate,(double)(dz->iparam[CRSPLICE] + dz->iparam[CRTAIL])/srate);
  1416. return DATA_ERROR;
  1417. }
  1418. }
  1419. // splice both ends of segment
  1420. if(dz->hastail) {
  1421. for(n=0;n<dz->iparam[CRSPLICE];n++) {
  1422. spliceval = (double)n/(double)dz->iparam[CRSPLICE];
  1423. ebuf[n] = (float)(ebuf[n] * spliceval);
  1424. }
  1425. for(n=0,m=eposend;n<dz->iparam[CRTAIL];n++,m--) {
  1426. spliceval = (double)n/(double)dz->iparam[CRTAIL];
  1427. spliceval *= spliceval; // Exponential fade
  1428. ebuf[m] = (float)(ebuf[m] * spliceval);
  1429. }
  1430. } else {
  1431. for(n=0,m=eposend;n<dz->iparam[CRSPLICE];n++,m--) {
  1432. spliceval = (double)n/(double)dz->iparam[CRSPLICE];
  1433. ebuf[n] = (float)(ebuf[n] * spliceval);
  1434. ebuf[m] = (float)(ebuf[m] * spliceval);
  1435. }
  1436. }
  1437. segstart_opos = opos;
  1438. // ADD INTO THE OUTPUT BUFFER, USING PERMUTATION OF OUTPUTA
  1439. // the goal chans are set by reading from the permutation of chans or chan-groups in "perm", counted by "permcnt"
  1440. if(sector < lastsector) {
  1441. // Writing to GROUPS of channels
  1442. thisperm = perm[permsize][permcnt]; // (thisperm * gpsize) gives lowest channel of current group
  1443. startchan = (dz->iparam[CRORIENT] + (thisperm * gpsize))%ochancnt; // with CRORIENT adding offset to start of group.
  1444. thischan = startchan;
  1445. for(n=0;n<oseglen;n++) {
  1446. for(chan = 0;chan < gpsize;chan++) { // Write to all channels in channel-group (all adjacent)
  1447. ochan = opos+thischan; // amplifying level by appropriate "balance" param
  1448. obuf[ochan] = (float)(obuf[ochan] + (ebuf[n] * balance[sector]));
  1449. thischan++; // going upwards round adjacent channels in group
  1450. thischan = thischan % ochancnt;
  1451. }
  1452. thischan = startchan; // Once one sample written to all output chans
  1453. opos += ochancnt; // reset start channel of group
  1454. } // and advance over ALL output-chans in output buffer
  1455. } else {
  1456. // Writing to INDIVIDUAL channels
  1457. thischan = perm[permsize][permcnt]; // Write to channel selected by current perm
  1458. for(n=0;n<oseglen;n++) {
  1459. ochan = opos+thischan;
  1460. obuf[ochan] = (float)(obuf[ochan] + (ebuf[n] * balance[sector]));
  1461. opos += ochancnt;
  1462. }
  1463. } // Due to contraction/expansion of segments by pitch-scattering
  1464. write_end = max(write_end,opos); // end of current output may not beyond end of previous writes
  1465. if(permsize == 2)
  1466. permcnt = !permcnt;
  1467. else if(++permcnt >= permsize) { // Once current perm of channels exhausted, reperm
  1468. doperm(perm[permsize],permsize,&lastperm,&lastperm2);
  1469. permcnt = 0;
  1470. }
  1471. // GET PARAMETERS FOR NEXT SEGMENT
  1472. // If output write time is scattered, do scattering
  1473. if(dz->param[CROSCAT] > 0.0) {
  1474. rval = drand48() * dz->param[CROSCAT]; // 0 to R
  1475. rval = 1.0 - rval; // Range 1 to 1-R
  1476. outstep = (int)round((double)outstep * rval);
  1477. }
  1478. // If output write time is stretched, do time-stretch
  1479. outstep = (int)round((double)outstep * dz->param[CROSTR]);
  1480. // outstep MUST advance
  1481. if(outstep == 0)
  1482. outstep++;
  1483. // Convert to count in output samples
  1484. outstep *= ochancnt;
  1485. // Advance to next write position
  1486. opos = segstart_opos + outstep;
  1487. // If next write will start beyond end of obuf, write outbuf, (Recursively in case there's a silent gap)
  1488. if((dz->iparam[CRDUR] > 0) && (opos + dz->total_samps_written >= dz->iparam[CRDUR])) {
  1489. curtailed = 1;
  1490. break;
  1491. }
  1492. while(opos >= obuflen) {
  1493. dz->process = BRASSAGE; // progress-bar set in terms of READ-samples, rather than written-samples.
  1494. if(passno == 0) {
  1495. for(n=0;n<obuflen;n++)
  1496. maxsamp = max(maxsamp,fabs(obuf[n]));
  1497. display_virtual_time(dz->total_samps_read,dz);
  1498. dz->total_samps_written += obuflen;
  1499. } else {
  1500. if(normaliser < 1.0) {
  1501. for(n=0;n<obuflen;n++)
  1502. obuf[n] = (float)(obuf[n] * normaliser);
  1503. }
  1504. if((exit_status = write_samps(obuf,obuflen,dz))<0)
  1505. return(exit_status);
  1506. }
  1507. dz->process = CRUMBLE;
  1508. memcpy((char *)obuf,(char *)oovbuf,obuflen * sizeof(float)); // Copy any overflow back into obuf
  1509. memset((char *)oovbuf,0,obuflen * sizeof(float)); // Zero the output-overflow buf
  1510. write_end -= obuflen; // Reset buffer pointers
  1511. opos -= obuflen;
  1512. }
  1513. // If ness, modify time where next input segment is cut
  1514. if(dz->param[CRISCAT] > 0.0) { // If time of input segment is scattered in time
  1515. rval = drand48() * dz->param[CRISCAT]; // Range 0 to +R
  1516. rval = 1.0 - rval; // Range 1 to 1-R
  1517. instep = (int)round((double)instep * rval);
  1518. }
  1519. // Advance to next input-read position
  1520. ipos += instep;
  1521. time = (double)((dz->total_samps_written+opos)/ochancnt)/srate;
  1522. }
  1523. if(curtailed)
  1524. break;
  1525. // Once next-read-position is beyond end of input buffer, readjust buffers and counters before next read
  1526. memcpy((char *)ibuf,(char *)iovbuf,dz->buflen * sizeof(float)); // Copy the read-ahead buffer back into ibuf
  1527. memset((char *)iovbuf,0,dz->buflen * sizeof(float)); // Zero the input-overflow buf
  1528. samples_before_bufstart += buffer_end;
  1529. ipos -= buffer_end;
  1530. }
  1531. // Once input file is exhausted, write any samples remaining in output buffer
  1532. if(write_end > 0) {
  1533. dz->process = BRASSAGE;
  1534. if(passno == 0) {
  1535. for(n=0;n<write_end;n++)
  1536. maxsamp = max(maxsamp,fabs(obuf[n]));
  1537. display_virtual_time(dz->insams[0],dz);
  1538. dz->total_samps_written += obuflen;
  1539. } else {
  1540. if(normaliser < 1.0) {
  1541. for(n=0;n<write_end;n++)
  1542. obuf[n] = (float)(obuf[n] * normaliser);
  1543. }
  1544. if(curtailed) {
  1545. endsplice = write_end/ochancnt;
  1546. if(dz->hastail) {
  1547. endsplice = min(endsplice,dz->iparam[CRTAIL]);
  1548. for(n = 0,m = write_end-ochancnt;n < endsplice;n++,m-=ochancnt) {
  1549. val = (double)n/(double)endsplice;
  1550. val *= val;
  1551. for(chan = 0; chan < ochancnt; chan++)
  1552. obuf[m+chan] = (float)(obuf[m+chan] * val);
  1553. }
  1554. } else {
  1555. endsplice = min(endsplice,dz->iparam[CRSPLICE]);
  1556. for(n = 0,m = write_end-ochancnt;n < endsplice;n++,m-=ochancnt) {
  1557. val = (double)n/(double)endsplice;
  1558. for(chan = 0; chan < ochancnt; chan++)
  1559. obuf[m+chan] = (float)(obuf[m+chan] * val);
  1560. }
  1561. }
  1562. }
  1563. if((exit_status = write_samps(obuf,write_end,dz))<0)
  1564. return(exit_status);
  1565. }
  1566. dz->process = CRUMBLE;
  1567. }
  1568. if(passno == 0) {
  1569. if(maxsamp > 0.95)
  1570. normaliser = 0.95/maxsamp;
  1571. else if(maxsamp <= FLTERR) {
  1572. sprintf(errstr,"No significant signal found in source file.\n");
  1573. return DATA_ERROR;
  1574. }
  1575. }
  1576. }
  1577. return FINISHED;
  1578. }
  1579. /********************************** CHECK_CRUMBLE_PARAM_VALIDITY_AND_CONSISTENCY ********************/
  1580. /* TW fixes Jan 2023 */
  1581. int check_crumble_param_validity_and_consistency(dataptr dz)
  1582. {
  1583. #define maxrandlenincr 1.5 // 1.5 is max random length increase
  1584. #define maxrandlenshrnk 0.5 // 0.5 is max random length decrease
  1585. int exit_status, ochans;
  1586. double processtime, srate = (double)dz->infile->srate, frqratio;
  1587. int minseglen, crstartsamps;
  1588. if(dz->mode == 1)
  1589. ochans = 16;
  1590. else
  1591. ochans = 8;
  1592. dz->param[CRSPLICE] *= MS_TO_SECS;
  1593. dz->iparam[CRSPLICE] = (int)ceil(dz->param[CRSPLICE] * srate);
  1594. crstartsamps = (int)ceil(dz->param[CRSTART] * srate);
  1595. if(dz->brksize[CRTAIL]) {
  1596. if((exit_status = read_value_from_brktable(dz->param[CRSTART],CRTAIL,dz))<0)
  1597. return exit_status;
  1598. }
  1599. if(dz->param[CRTAIL] > 0.0) {
  1600. dz->param[CRTAIL] = max(dz->param[CRTAIL],dz->application->lo[CRSPLICE] * 2.0);
  1601. if(dz->iparam[CRTAIL] + crstartsamps >= dz->insams[0]) {
  1602. sprintf(errstr,"Exponetial tail too long with the start segment.\n");
  1603. return DATA_ERROR;
  1604. }
  1605. }
  1606. dz->hastail = 1;
  1607. dz->notailanywhere = 0;
  1608. if(dz->brksize[CRTAIL]) {
  1609. if((exit_status = get_maxvalue_in_brktable(&(dz->param[CRTAIL]),CRTAIL,dz))<0)
  1610. return exit_status;
  1611. }
  1612. if(dz->param[CRTAIL] > 0.0) { // Working with MAX specified tail-length ...
  1613. dz->param[CRTAIL] = max(dz->param[CRTAIL],dz->application->lo[CRSPLICE] * 2.0); // ensure tail is set at at-least double minsplicelen
  1614. dz->iparam[CRTAIL] = (int)ceil(dz->param[CRTAIL] * MS_TO_SECS * srate); // to compensate for tail decay being exponential
  1615. } else {
  1616. dz->hastail = 0;
  1617. dz->notailanywhere = 1;
  1618. dz->iparam[CRTAIL] = dz->iparam[CRSPLICE];
  1619. }
  1620. processtime = dz->param[CRSTART] + dz->param[CRSTEP1] + dz->param[CRSTEP2];
  1621. if(dz->mode==1)
  1622. processtime += dz->param[CRSTEP3];
  1623. if(processtime >= dz->duration) {
  1624. sprintf(errstr,"Sum of durations of splitting processes extends beyond end of input file.\n");
  1625. return DATA_ERROR;
  1626. }
  1627. if(dz->brksize[CRRAND]) {
  1628. if((exit_status = get_maxvalue_in_brktable(&(dz->param[CRRAND]),CRRAND,dz))<0)
  1629. return exit_status;
  1630. }
  1631. if(dz->brksize[CRSIZE]) {
  1632. if((exit_status = get_maxvalue_in_brktable(&(dz->param[CRSIZE]),CRSIZE,dz))<0)
  1633. return exit_status;
  1634. }
  1635. if(dz->brksize[CRPSCAT]) {
  1636. if((exit_status = get_maxvalue_in_brktable(&(dz->param[CRPSCAT]),CRPSCAT,dz))<0)
  1637. return exit_status;
  1638. }
  1639. frqratio = pow(2.0,dz->param[CRPSCAT]/SEMITONES_PER_OCTAVE); // transpose max down, increases seglen by +ve frq ratio
  1640. dz->maxinseg = (int)ceil(dz->param[CRSIZE] * frqratio * srate * maxrandlenincr);
  1641. if(dz->hastail) {
  1642. dz->maxinseg += (int)ceil(dz->iparam[CRTAIL] * frqratio); // CRTAIL holds maxvalue, CRPSCAT minvalue, at present
  1643. }
  1644. dz->maxinseg *= 2; // LARGE SAFETY MARGIN!!
  1645. dz->maxoutseg = dz->maxinseg * ochans; // max-segsize in outputbuf
  1646. if(dz->brksize[CRSIZE]) {
  1647. if((exit_status = get_minvalue_in_brktable(&(dz->param[CRSIZE]),CRSIZE,dz))<0)
  1648. return exit_status;
  1649. } // min-segsize in inputbuf
  1650. minseglen = (int)ceil((dz->param[CRSIZE]/frqratio) * srate * maxrandlenshrnk);
  1651. dz->warned = 0;
  1652. if(minseglen <= dz->iparam[CRSPLICE] + dz->iparam[CRTAIL]) { // NB, CRSPLICE is fixed and CRTAIL has been set at its maxvalue
  1653. dz->warned = 1;
  1654. fprintf(stdout,"WARNING: Minimum segment length (after any transpositions) may be too short for splices (and any tail).\n");
  1655. fflush(stdout);
  1656. }
  1657. if(dz->param[CRDUR] > 0.0 && dz->param[CRDUR] < dz->param[CRSTART]) {
  1658. fprintf(stdout,"WARNING: Terminate time (%lf) set before before disintegration begins (%lf).\n",dz->param[CRDUR],dz->param[CRSTART]);
  1659. fflush(stdout);
  1660. } else {
  1661. dz->iparam[CRDUR] = (int)round(dz->param[CRDUR] * srate);
  1662. dz->iparam[CRDUR] *= ochans;
  1663. }
  1664. dz->iparam[CRORIENT]--; // Change from 1-8 to 0-7 numbering (1-16, to 0-15)
  1665. return FINISHED;
  1666. }
  1667. /******************************** CREATE_CRUMBLE_SNDBUFS *****************/
  1668. int create_crumble_sndbufs(dataptr dz)
  1669. {
  1670. int bigbufsize, framesize, orig_framesize, frameunit, output_framesize, orig_output_framesize, outbufsize, outchans;
  1671. if(dz->sbufptr == 0 || dz->sampbuf==0) {
  1672. sprintf(errstr,"buffer pointers not allocated: create_sndbufs()\n");
  1673. return(PROGRAM_ERROR);
  1674. }
  1675. if(dz->mode == 1)
  1676. outchans = 16;
  1677. else
  1678. outchans = 8;
  1679. frameunit = outchans + MONO; // frame must be multiple of changroupsize of output & input;
  1680. orig_framesize = F_SECSIZE * frameunit; // frame must also be a multiple of sectorsize
  1681. framesize = orig_framesize;
  1682. orig_output_framesize = F_SECSIZE * outchans; // Outputbuffer (only) framesize
  1683. output_framesize = orig_output_framesize;
  1684. while(output_framesize <= dz->maxoutseg) { // outputbuffer must accomodate the maximum-size of segment to be written
  1685. output_framesize += orig_output_framesize;
  1686. framesize += orig_framesize;
  1687. }
  1688. framesize *= 2; // frame must accomodate double buffer for input, and for output
  1689. frameunit *= 2;
  1690. bigbufsize = (int)(size_t) Malloc(-1);
  1691. dz->buflen = bigbufsize / sizeof(float); // Ensure buffer contains an integer number of frames
  1692. dz->buflen = (dz->buflen / framesize) * framesize;
  1693. bigbufsize = dz->buflen * sizeof(float);
  1694. if(bigbufsize <= 0) {
  1695. dz->buflen = framesize;
  1696. bigbufsize = dz->buflen * sizeof(float);
  1697. }
  1698. dz->buflen = dz->buflen/frameunit; // Get TRUE (input) buffer size
  1699. outbufsize = dz->buflen * outchans; // Get output buffer size
  1700. bigbufsize = ((dz->buflen * 2) + (outbufsize * 3)) * sizeof(float);
  1701. /* 2023 */
  1702. bigbufsize += dz->maxinseg * sizeof(float); // add in memory for segment-enveloping buffer
  1703. if(bigbufsize <= 0) {
  1704. sprintf(errstr,"TOO MUCH MEMORY REQUIRED for sound buffers.\n");
  1705. return(PROGRAM_ERROR);
  1706. }
  1707. if((dz->bigbuf = (float *)malloc(bigbufsize)) == NULL) {
  1708. sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
  1709. return(PROGRAM_ERROR);
  1710. }
  1711. dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf; // input
  1712. dz->sbufptr[1] = dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen; // input overflow
  1713. dz->sbufptr[2] = dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen; // output
  1714. dz->sbufptr[3] = dz->sampbuf[3] = dz->sampbuf[2] + outbufsize; // output overflow
  1715. dz->sbufptr[4] = dz->sampbuf[4] = dz->sampbuf[3] + outbufsize; // enveloping buffer
  1716. dz->sampbuf[5] = dz->sampbuf[4] + outbufsize + dz->maxinseg; //2023
  1717. return(FINISHED);
  1718. }
  1719. /*************************** PERMUTE_CHUNKS ***************************
  1720. *
  1721. * "lastperm2" is only set to a non-negative value when we cross a sector boundary.
  1722. * At that point there are 2 previous channels or channel-groups to avoid when selecting next chan or group.
  1723. * Once we are in lastsector (i.e. sending sigs to individual channels)
  1724. * lastperm stays stuck at -1 and does not affect the perm calculations.
  1725. */
  1726. void doperm(int *perm,int permsize,int *lastperm,int *lastperm2)
  1727. {
  1728. int n, t;
  1729. if(*lastperm2 >= 0) { // If we've just changed sector, need to check 1st TWO perm items
  1730. // are not in any of the channels in the previous chan-group used.
  1731. do {
  1732. for(n=0;n<permsize;n++) {
  1733. t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
  1734. if(t==n)
  1735. prefix(perm,permsize,n);
  1736. else
  1737. insert(perm,permsize,n,t);
  1738. } // Avoid 1st * 2nd item in perm equaling last item-pair in previous perm
  1739. } while(perm[0] == *lastperm || perm[0] == *lastperm2 || perm[1] == *lastperm || perm[1] == *lastperm2);
  1740. *lastperm = perm[permsize-1]; // But once first perm generated, we only need to avoid 1 chan(gp).
  1741. *lastperm2 = -1; // So set lastperm2 to an impossible val, which causes 2nd do loop to be called, instead.
  1742. } else {
  1743. do { // Comparing same-grouping-size perm. Only need to check ONE perm item.
  1744. for(n=0;n<permsize;n++) {
  1745. t = (int)(drand48() * (double)(n+1)); /* TRUNCATE */
  1746. if(t==n)
  1747. prefix(perm,permsize,n);
  1748. else
  1749. insert(perm,permsize,n,t);
  1750. }
  1751. } while(perm[0] == *lastperm); // Avoid 1st item in next perm equaling last item in previous perm
  1752. }
  1753. }
  1754. /****************************** INSERT ****************************/
  1755. void insert(int *perm,int permsize,int n,int t)
  1756. {
  1757. shuflup(perm,permsize,t+1);
  1758. perm[t+1] = n;
  1759. }
  1760. /****************************** PREFIX ****************************/
  1761. void prefix(int *perm,int permsize,int n)
  1762. {
  1763. shuflup(perm,permsize,0);
  1764. perm[0] = n;
  1765. }
  1766. /****************************** SHUFLUP ****************************/
  1767. void shuflup(int *perm,int permsize,int k)
  1768. {
  1769. int n;
  1770. for(n = permsize-1; n > k; n--)
  1771. perm[n] = perm[n-1];
  1772. }
  1773. /****************************** GET_MODE *********************************/
  1774. int get_the_mode_from_cmdline(char *str,dataptr dz)
  1775. {
  1776. char temp[200], *p;
  1777. if(sscanf(str,"%s",temp)!=1) {
  1778. sprintf(errstr,"Cannot read mode of program.\n");
  1779. return(USAGE_ONLY);
  1780. }
  1781. p = temp + strlen(temp) - 1;
  1782. while(p >= temp) {
  1783. if(!isdigit(*p)) {
  1784. fprintf(stderr,"Invalid mode of program entered.\n");
  1785. return(USAGE_ONLY);
  1786. }
  1787. p--;
  1788. }
  1789. if(sscanf(str,"%d",&dz->mode)!=1) {
  1790. fprintf(stderr,"Cannot read mode of program.\n");
  1791. return(USAGE_ONLY);
  1792. }
  1793. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  1794. fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  1795. return(USAGE_ONLY);
  1796. }
  1797. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  1798. return(FINISHED);
  1799. }