texture4.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476
  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. /* floatsam version : no changes */
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <float.h>
  25. #include <structures.h>
  26. #include <tkglobals.h>
  27. #include <globcon.h>
  28. #include <processno.h>
  29. #include <modeno.h>
  30. #include <arrays.h>
  31. #include <texture.h>
  32. #include <cdpmain.h>
  33. #include <sfsys.h>
  34. #include <osbind.h>
  35. //#if defined unix || defined __GNUC__
  36. #define round(x) lround((x))
  37. //#endif
  38. /**** ALL FUNCTIONS WHICH ARE GLOBAL TO ALL PROCESS FUNCTIONS TYPES ***/
  39. /* Functions which are global to all texture applications.
  40. */
  41. static void orn_subzero(double *thistime,noteptr phrlastnote,noteptr *phrasenote,
  42. double *timeadjust,double multiplier,int *gpsize);
  43. static int getmtfampstep
  44. (double amp,double framp,double *ampstep,unsigned char *amptype,
  45. unsigned char amptypestor,unsigned char amptypecnt,int gpsize,dataptr dz);
  46. static int space_gpnote(noteptr thisnote,int gpsize,dataptr dz);
  47. static int sp_scatter(noteptr mnote,dataptr dz);
  48. static int pre_place(noteptr thisnote,int gpsize,dataptr dz);
  49. static int post_place(noteptr thisnote,int gpsize,dataptr dz);
  50. static int read_direction(int shi,noteptr *shadow,int shadowsize);
  51. static int do_ev_ins(unsigned char *thisinstr,double thistime,dataptr dz);
  52. static int do_ev_amp(double *thisamp,double thistime,dataptr dz);
  53. static int do_ev_dur(double *thisdur,double thistime,dataptr dz);
  54. static int getdirampstep
  55. (double amp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz);
  56. static int getampstep
  57. (double *ampstep,double amp,unsigned char *amptype,int gpsize,unsigned char amptypecnt,
  58. unsigned char amptypestor,dataptr dz);
  59. static int get_dec_or_orn_pos(dataptr dz);
  60. static int subzero(double *thistime,double gpdense,int *gpsize);
  61. static noteptr reverse_search_for_time(noteptr start,double reftime);
  62. static void move_notelist_item(noteptr a,noteptr b);
  63. static double setup_first_notelist_time(noteptr *base);
  64. static int reset_mtfhead(motifptr mtf);
  65. static int post_place(noteptr thisnote,int gpsize,dataptr dz);
  66. static int getmtfdirampstep
  67. (double amp,double framp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz);
  68. static void cyclicperm(dataptr dz);
  69. static void hinsert(int m,int t,int *perm,int permlen);
  70. static void hprefix(int m,int *perm,int permlen);
  71. static void hshuflup(int k,int *perm,int permlen);
  72. /***************************** OCTADJUST *****************************
  73. *
  74. * Check for range overflow of pitch.
  75. */
  76. double octadjust(double thispitch)
  77. {
  78. if(thispitch>MIDITOP)
  79. thispitch -= SEMITONES_PER_OCTAVE;
  80. if(thispitch<MIDIBOT)
  81. thispitch += SEMITONES_PER_OCTAVE;
  82. return(thispitch);
  83. }
  84. /***************************** DO_AMP_INSTR_DUR ************************************/
  85. int do_amp_instr_dur
  86. (double *thisamp,unsigned char *thisinstr,double *thisdur,noteptr tsetnote,double thistime,dataptr dz)
  87. {
  88. int exit_status;
  89. if((exit_status = do_ev_amp(thisamp,thistime,dz))<0)
  90. return(exit_status);
  91. tsetnote->amp = (float)(*thisamp);
  92. if((exit_status = do_ev_ins(thisinstr,thistime,dz))<0)
  93. return(exit_status);
  94. tsetnote->instr = *thisinstr;
  95. if((exit_status = do_ev_dur(thisdur,thistime,dz))<0)
  96. return(exit_status);
  97. tsetnote->dur = (float)(*thisdur);
  98. return(FINISHED);
  99. }
  100. /********************** DO_EV_INS *******************************
  101. *
  102. * Set instrument of event (not group etc.).
  103. *
  104. * (0) If instruments in ornament or decoration are to be relative to
  105. * input instr, return this input instrument.
  106. * (1) If there is a pre-existing timed set (pretimed = 1).
  107. * (2) Negative value causes original value to be replaced
  108. * by orig + abs(neg value).
  109. * Zero value, by default, causes orig value to be retained.
  110. */
  111. int do_ev_ins(unsigned char *thisinstr,double thistime,dataptr dz)
  112. {
  113. int exit_status;
  114. int instrval;
  115. if(dz->process == SIMPLE_TEX && dz->vflag[CYCLIC_TEXFLAG]) {
  116. if(dz->itemcnt == dz->infilecnt)
  117. dz->itemcnt = 0;
  118. if(dz->vflag[PERM_TEXFLAG]) {
  119. if(dz->itemcnt == 0)
  120. cyclicperm(dz);
  121. *thisinstr = (unsigned char)dz->peakno[dz->itemcnt];
  122. } else {
  123. *thisinstr = (unsigned char)dz->itemcnt;
  124. }
  125. dz->itemcnt++;
  126. } else {
  127. if((exit_status = igetvalue(TEXTURE_INSHI,TEXTURE_INSLO,thistime,PM_INSNO,&instrval,dz))<0)
  128. return(exit_status);
  129. *thisinstr = (unsigned char)instrval;
  130. }
  131. return(FINISHED);
  132. }
  133. /********************** DO_EV_AMP ********************************/
  134. int do_ev_amp(double *thisamp,double thistime,dataptr dz)
  135. {
  136. int exit_status;
  137. if((exit_status = getvalue(TEXTURE_MAXAMP,TEXTURE_MINAMP,thistime,PM_AMP,thisamp,dz))<0)
  138. return(exit_status);
  139. *thisamp *= dz->param[TEXTURE_ATTEN];
  140. if(*thisamp>MIDITOP + 0.5) {
  141. sprintf(errstr,"TEXTURE: amplitude [%.1f] out of midirange at time %.2f\n",*thisamp,thistime);
  142. return(DATA_ERROR);
  143. }
  144. return(FINISHED);
  145. }
  146. /********************** DO_EV_DUR ********************************/
  147. int do_ev_dur(double *thisdur,double thistime,dataptr dz)
  148. {
  149. int exit_status;
  150. if((exit_status = getvalue(TEXTURE_MAXDUR,TEXTURE_MINDUR,thistime,PM_DUR,thisdur,dz))<0)
  151. return(exit_status);
  152. return(FINISHED); /* 4 */
  153. }
  154. /************************ MAKE_SHADOW ****************************
  155. *
  156. * Store addresses of original tset notes.
  157. */
  158. int make_shadow(motifptr tset,int *shadowsize,noteptr **shadow)
  159. {
  160. noteptr *sh, thisnote = tset->firstnote;
  161. int n;
  162. *shadowsize = 0;
  163. while(thisnote!=(noteptr)0) {
  164. (*shadowsize)++;
  165. thisnote = thisnote->next;
  166. }
  167. if((sh = *shadow = (noteptr *)malloc((*shadowsize) * sizeof(noteptr)))==NULL) {
  168. sprintf(errstr,"INSUFFICIENT MEMORY for shadow.\n");
  169. return(MEMORY_ERROR);
  170. }
  171. thisnote = tset->firstnote;
  172. n = 0;
  173. while(thisnote!=(noteptr)0) {
  174. sh[n++] = thisnote;
  175. thisnote = thisnote->next;
  176. }
  177. return(FINISHED);
  178. }
  179. /************************ ERASE_SHADOW ****************************
  180. *
  181. * Erase original tset from resultant list.
  182. *
  183. * (0) Assuming shadow starts at start of tset, if first note of
  184. * shadow is deleted, del_note automatically resets motifptr (tset)
  185. * to next note (and so on).
  186. * (1) In case shadow started AFTER start of tset (should be impossible!!)
  187. * reset pointer to start of remaining motif !
  188. */
  189. int erase_shadow(int shadowsize,noteptr *shadow,motifptr tset)
  190. {
  191. int n;
  192. noteptr thisnote;
  193. for(n=0;n<shadowsize;n++) /* 0 */
  194. del_note(shadow[n],tset);
  195. if((thisnote = tset->firstnote->last)!=(noteptr)0) { /* 1 */
  196. sprintf(errstr,"TEXTURE: erase_shadow(): First note of shadow NOT first note of tset.\n"
  197. "This should never happen\n");
  198. return(PROGRAM_ERROR);
  199. /**** REMOVED FOLLOWING AUTO-CORRECTION CODE : OCT 1997 *****
  200. while(thisnote->last!=(noteptr)0)
  201. thisnote = thisnote->last;
  202. tset->firstnote = thisnote;
  203. ****/
  204. }
  205. return(FINISHED);
  206. }
  207. /************************ SETUP_DECOR ****************************/
  208. void setup_decor(double *pptop,double *ppbot,int *shadindex,noteptr *tsetnote,dataptr dz)
  209. {
  210. *pptop = MIDITOP;
  211. *ppbot = MIDIBOT;
  212. if(dz->vflag[WHICH_CHORDNOTE]==DECOR_HIGHEST)
  213. *tsetnote = gethipitch(*tsetnote,shadindex);
  214. }
  215. /**************************** SETUP_ORNAMENT *********************************/
  216. int setup_ornament
  217. (double *timeadjust,double *thistime,int *gpsize,noteptr *phrlastnote,
  218. double multiplier,noteptr *phrasenote,int phrno,dataptr dz)
  219. {
  220. int exit_status;
  221. double origtime;
  222. if((exit_status = get_dec_or_orn_pos(dz))<0)
  223. return(exit_status);
  224. *timeadjust = 0.0;
  225. if(dz->vflag[IS_PRE]) {
  226. origtime = *thistime;
  227. if((*thistime -= (phrlastnote[phrno])->ntime * multiplier)<0.0) {
  228. *thistime = origtime;
  229. orn_subzero(thistime,phrlastnote[phrno],phrasenote,timeadjust,multiplier,gpsize);
  230. }
  231. }
  232. return(FINISHED);
  233. }
  234. /**************************** SET_MOTIF_AMP *********************************/
  235. int set_motif_amp
  236. (noteptr tsetnote,double *thisamp,int gpsize,double ampstep,noteptr phrasenote,double rangemult,
  237. double *phraseamp,int phrno,unsigned char amptype)
  238. {
  239. double ampdif;
  240. if(amptype==CRESC) {
  241. *thisamp -= (double)(gpsize) * ampstep;
  242. ampdif = (phraseamp[phrno] - phrasenote->amp) * rangemult;
  243. tsetnote->amp = (float)(*thisamp - ampdif);
  244. }
  245. return(FINISHED);
  246. }
  247. /**************************** SET_ORNAMENT_AMP *********************************/
  248. int set_ornament_amp
  249. (double *phraseamp,noteptr *phrlastnote,double *thisamp,
  250. noteptr phrasenote,int phrno,noteptr tsetnote,
  251. double ampstep,double rangemult,int gpsize,dataptr dz)
  252. {
  253. double ampdif;
  254. if(dz->vflag[IS_PRE])
  255. ampdif=(phraseamp[phrno]-phrlastnote[phrno]->amp) * rangemult;
  256. else
  257. ampdif=(phraseamp[phrno]-phrasenote->amp) * rangemult;
  258. tsetnote->amp -= (float)ampdif;
  259. if(ampstep>0.0) /* CRESCENDO */
  260. *thisamp -= (double)(gpsize+1) * ampstep;
  261. return(FINISHED);
  262. }
  263. /**************************** CHECK_NEXT_PHRASENOTE_EXISTS *********************************/
  264. int check_next_phrasenote_exists(noteptr *phrasenote,int texflag,dataptr dz)
  265. {
  266. if(texflag & IS_MOTIFS) {
  267. if((*phrasenote = (*phrasenote)->next)==(noteptr)0) {
  268. sprintf(errstr,"TEXTURE: Accounting Problem in check_next_phrasenote_exists()\n");
  269. return(PROGRAM_ERROR);
  270. }
  271. } else if (texflag & IS_ORNATE){
  272. if(*phrasenote==(noteptr)0) {
  273. sprintf(errstr,"TEXTURE: 1st Accounting Problem in check_next_phrasenote_exists()\n");
  274. return(PROGRAM_ERROR);
  275. }
  276. if(dz->vflag[IS_PRE] && ((*phrasenote)->next==(noteptr)0)) {
  277. sprintf(errstr,"TEXTURE: 2nd Accounting Problem in check_next_phrasenote_exists()\n");
  278. return(PROGRAM_ERROR);
  279. }
  280. }
  281. return(CONTINUE);
  282. }
  283. /************************* GETNEXTEVENT_TO_DECORATE ***************************
  284. *
  285. * Get the next event in list, i.e. skip over simultaneous events
  286. * (e.g. chords).
  287. *
  288. * (0) If flagged as 2, ornaments/decorations are attached to EVERY note
  289. * so the next event is just the next note in the tset.
  290. * OTHERWISE we search for the next event AT A NEW TIME.
  291. * (1) If flagged, force a search for the highest note of a simultaneous
  292. * group (chord). Hence ornament/dec attaches to highest note.
  293. * Otherwise, ornament attached to first listed note of chord in input
  294. * data.
  295. */
  296. noteptr getnextevent_to_decorate(noteptr tsetnote,int *shaddoindex,dataptr dz)
  297. {
  298. if(dz->vflag[WHICH_CHORDNOTE]==DECOR_EVERY) /* 0 */
  299. return(tsetnote->next);
  300. while(tsetnote->next!=(noteptr)0) {
  301. tsetnote = tsetnote->next;
  302. (*shaddoindex)++;
  303. if(!flteq((double)tsetnote->ntime,(double)tsetnote->last->ntime)) {
  304. if(dz->vflag[WHICH_CHORDNOTE]==DECOR_HIGHEST)
  305. tsetnote = gethipitch(tsetnote,shaddoindex); /* 1 */
  306. return(tsetnote);
  307. }
  308. }
  309. return((noteptr)0);
  310. }
  311. /************************** GETNOTETIME ********************************
  312. *
  313. * Get actual time of note, from time of tset note, and time of motif
  314. * or ornament note.
  315. * (a) Time is set by an offset from the tset-note, THROUGHOUT each
  316. * motif-placement. The offset for each note is its position in the
  317. * original note (which have been set relative to zero by set_mtfs())
  318. * times the multiplier, with an adjustment if we're actually using
  319. * less than the whole motif for some reason.
  320. * (b) Time may need to be quantised.
  321. * (c) Time of note is this tset-note + offset.
  322. */
  323. double getnotetime(noteptr phrasenote,double thistime,double multiplier,double timeadjust,dataptr dz)
  324. {
  325. int qunits;
  326. double timestep = ((double)phrasenote->ntime - timeadjust) * (double)multiplier; /* a */
  327. double thisgrid;
  328. if(dz->param[TEX_PHGRID]>0.0) {
  329. /* NEW 2000 */
  330. thisgrid = dz->param[TEX_PHGRID] * MS_TO_SECS;
  331. qunits = round(timestep/thisgrid); /* b */
  332. timestep = (double)(qunits*thisgrid);
  333. }
  334. return(thistime + timestep); /* c */
  335. }
  336. /************************ GETMTFDUR **********************************/
  337. int getmtfdur(noteptr tsetnote,noteptr phrasenote,double *dur,double multiplier,dataptr dz)
  338. {
  339. if(dz->vflag[DONT_KEEP_MTFDUR])
  340. *dur = tsetnote->dur;
  341. else
  342. *dur = phrasenote->dur * multiplier;
  343. if(flteq(*dur,0.0)) {
  344. sprintf(errstr,"TEXTURE: Problem 3 in getmtfdur(): Zero duration\n");
  345. return(PROGRAM_ERROR);
  346. }
  347. return(FINISHED);
  348. }
  349. /***************************** ORN_OR_MTF_AMP_SETUP ************************************/
  350. int orn_or_mtf_amp_setup
  351. (int ampdirected,double *phrange,int phrno,double thisamp,int gpsize,double *rangemult,double *ampstep,
  352. unsigned char *amptype,unsigned char amptypestor,unsigned char amptypecnt,dataptr dz)
  353. {
  354. int exit_status;
  355. double kk;
  356. if(phrange[phrno]>=thisamp) {
  357. kk = (double)phrange[phrno]*((double)(gpsize+1)/(double)gpsize);
  358. *rangemult = (double)thisamp / kk;
  359. *ampstep = 0.0;
  360. } else {
  361. if(ampdirected) {
  362. if((exit_status = getmtfdirampstep(thisamp,phrange[phrno],amptypecnt,ampstep,gpsize,dz))<0)
  363. return(exit_status);
  364. } else {
  365. if((exit_status = getmtfampstep(thisamp,phrange[phrno],ampstep,amptype,amptypestor,amptypecnt,gpsize,dz))<0)
  366. return(exit_status);
  367. }
  368. *rangemult = 1.0;
  369. }
  370. return(FINISHED);
  371. }
  372. /**************************** DO_MTF_PARAMS *******************************/
  373. int do_mtf_params
  374. (noteptr thisnote,double thisamp,noteptr phrasenote,noteptr tsetnote,
  375. double ampdif,double notetime,double multiplier,dataptr dz)
  376. {
  377. int exit_status;
  378. double duration;
  379. thisnote->amp = (float)(thisamp - ampdif);
  380. if((exit_status = getmtfdur(tsetnote,phrasenote,&duration,multiplier,dz))<0)
  381. return(exit_status);
  382. thisnote->dur = (float)duration;
  383. if((exit_status = do_grp_ins(tsetnote->instr,&(thisnote->instr),dz))<0)
  384. return(exit_status);
  385. thisnote->motioncentre = tsetnote->motioncentre;
  386. thisnote->ntime = (float)notetime;
  387. return(FINISHED);
  388. }
  389. /***************************** SETUP_MOTIF_OR_ORNAMENT ************************************/
  390. int setup_motif_or_ornament
  391. (double thistime,double *multiplier,int *phrno,noteptr *phrasenote,motifptr *phrase,dataptr dz)
  392. {
  393. int exit_status;
  394. if((exit_status = getvalue(TEX_MULTHI,TEX_MULTLO,thistime,PM_MULT,multiplier,dz))<0)
  395. return(exit_status);
  396. if((exit_status = doperm((int)dz->tex->phrasecnt,PM_WHICH,phrno,dz))<0)
  397. return(exit_status);
  398. *phrasenote = phrase[*phrno]->firstnote;
  399. return(FINISHED);
  400. }
  401. /****************************** POSITION_AND_SIZE_DECORATION **********************************/
  402. int position_and_size_decoration
  403. (double *thistime,double tsettime,double gpdense,int *gpsize,dataptr dz)
  404. {
  405. int exit_status;
  406. if((exit_status = get_dec_or_orn_pos(dz))<0)
  407. return(exit_status);
  408. if(dz->vflag[IS_PRE]) {
  409. if((*thistime -= gpdense * (double)((*gpsize) + 1))< -gpdense) {
  410. *thistime = tsettime;
  411. if((exit_status = subzero(thistime,gpdense,gpsize))<0)
  412. return(exit_status);
  413. }
  414. }
  415. return(FINISHED);
  416. }
  417. /****************************** SET_DECOR_AMP **********************************/
  418. int set_decor_amp
  419. (int ampdirected,double *thisamp,double *ampstep,int gpsize,
  420. unsigned char *amptype,unsigned char amptypecnt,unsigned char amptypestor,dataptr dz)
  421. {
  422. int exit_status;
  423. if(ampdirected) {
  424. if((exit_status = getdirampstep(*thisamp,amptypecnt,ampstep,gpsize,dz))<0)
  425. return(exit_status);
  426. } else {
  427. if((exit_status = getampstep(ampstep,*thisamp,amptype,gpsize,amptypecnt,amptypestor,dz))<0)
  428. return(exit_status);
  429. }
  430. if(*ampstep>0.0)
  431. *thisamp -= (double)(gpsize+1) * (*ampstep);
  432. return(FINISHED);
  433. }
  434. /****************************** SET_GROUP_AMP **********************************/
  435. int set_group_amp
  436. (noteptr tsetnote,double *thisamp,unsigned char *amptype, double *ampstep,int gpsize,
  437. unsigned char amptypecnt,unsigned char amptypestor,dataptr dz)
  438. {
  439. int exit_status;
  440. if((exit_status = getampstep(ampstep,*thisamp,amptype,gpsize,amptypecnt,amptypestor,dz))<0)
  441. return(exit_status);
  442. if(*amptype==CRESC) {
  443. *thisamp -= (double)(gpsize) * (*ampstep);
  444. tsetnote->amp = (float)(*thisamp);
  445. }
  446. return(FINISHED);
  447. }
  448. /* LOCAL TO THESE GLOBALS */
  449. /****************************** ORN_SUBZERO *******************************
  450. *
  451. * Readjust the groupsize and the pointer to first note of phrase, where
  452. * otherwise phrase would start before zero.
  453. *
  454. * (1) Note the endtime of the phrase.
  455. * (2) For each note in the phrase.
  456. * (3) Find the duration of the phrase FROM THIS NOTE, by subtracting time of
  457. * current note from end (total) time, and adjusting by multiplier.
  458. * (4) If the duration of phrase from here, would put it's start after
  459. * zero-time, break from loop.
  460. * (5) Count number of notes rejected, and go to next phrase note.
  461. * (6) If we're at end of phrase, none of it's notes fall after zero time,
  462. * so return a gpsize of 0.
  463. * (7) Otherwise reset the event time (mifitime) to start of the group or
  464. * part-group which 'thisnote' points to.
  465. * (8) Resert the phrase pointer to point at this note of the phrase.
  466. * (9) When note times are finally calculated, timeadjust will reset all
  467. * the note times WITHIN the ornament to run from the note from
  468. * which we're starting, rather than the true start, by subtracting
  469. * 'timeadjust'.
  470. * (10) Return a size for the group reduced by the number of rejected notes.
  471. */
  472. void orn_subzero
  473. (double *thistime,noteptr phrlastnote,noteptr *phrasenote,double *timeadjust,double multiplier,int *gpsize)
  474. {
  475. double endtime = phrlastnote->ntime; /* 1 */
  476. double phrdur = 0.0;
  477. int cnt = 0;
  478. noteptr thisnote = *phrasenote;
  479. while(thisnote!=(noteptr)0) { /* 2 */
  480. phrdur = (endtime - thisnote->ntime) * multiplier; /* 3 */
  481. if(*thistime - phrdur >= 0.0) /* 4 */
  482. break;
  483. cnt++; /* 5 */
  484. thisnote = thisnote->next;
  485. }
  486. if(thisnote==(noteptr)0) {
  487. *gpsize = 0; /* 6 */
  488. return;
  489. } else {
  490. *thistime -= phrdur; /* 7 */
  491. *phrasenote = thisnote; /* 8 */
  492. *timeadjust = thisnote->ntime; /* 9 */
  493. }
  494. *gpsize -= cnt;
  495. return; /* 10 */
  496. }
  497. /*************************** GETMTFAMPSTEP ******************************
  498. *
  499. * Select flat, cresc or decresc, from available types, for motifs.
  500. *
  501. * (0) If the amplitude is bigger than the size of amprise and the
  502. * range of the phrase, taken together, amprise is OK as it is.
  503. * (00) Otherwise, amprise (set as ampstep at this point) is the amount
  504. * of the total amplitude left when the amplitude range of the phrase
  505. * has been subtracted. This ensures that no note of the phrase
  506. * can possibly end up below zero.
  507. * (1) IF the cresc will be from zero, clrzamp is 1, and this makes
  508. * the amplitude steps a little smaller, so that 1 of the notes
  509. * in sequence cannot be at amplitude zero.
  510. * OTHERWISE, clrzamp = 0, and ampstep is as normal.
  511. */
  512. int getmtfampstep(double amp,double framp,double *ampstep,unsigned char *amptype,
  513. unsigned char amptypestor,unsigned char amptypecnt,int gpsize,dataptr dz)
  514. {
  515. int exit_status;
  516. int clrzamp = 0;
  517. int k;
  518. if((exit_status = doperm((int)amptypecnt,PM_GPCNTR,&k,dz))<0)
  519. return(exit_status);
  520. if((exit_status=gettritype(k,amptypestor,amptype))<0)
  521. return(exit_status);
  522. if(*amptype==FLAT) { /**** FLAT *****/
  523. *ampstep =0.0;
  524. } else {
  525. if(amp>(dz->param[TEX_AMPRISE] + framp)) /* 0 */
  526. *ampstep = dz->param[TEX_AMPRISE];
  527. else {
  528. *ampstep = amp - framp; /* 00 */
  529. clrzamp = 1;
  530. }
  531. *ampstep /= (double)(gpsize+clrzamp); /* 1 */
  532. if(*amptype==DECRESC) /** DECRESCENDO **/
  533. *ampstep = -(*ampstep);
  534. }
  535. return(FINISHED);
  536. }
  537. /************************************************************************
  538. *
  539. * Calculating spatial orientation of motifs,groups,ornaments,decorations.
  540. */
  541. /**************************** SETSPACE *******************************/
  542. int setspace(noteptr tsetnote,noteptr thisnote,int gpsize,dataptr dz)
  543. {
  544. int exit_status;
  545. if(dz->iparam[TEX_GPSPACE]!=IS_STILL) {
  546. if((exit_status = space_gpnote(thisnote,gpsize,dz))<0)
  547. return(exit_status);
  548. } else
  549. thisnote->spacepos = tsetnote->spacepos;
  550. return(FINISHED);
  551. }
  552. /***************************** SPACE_GPNOTE *******************************
  553. *
  554. * (1) OUTSIDE THE GROUP- OR PHRASE-MAKING LOOP
  555. * (a) Need to know gpsize, dectype(is_post?), gpsprange
  556. * (which MUST be +ve!).
  557. * (b) Need to run 'init_group_spatialisation()' to establish spinit, & hence
  558. * range modifications etc.
  559. *
  560. * Then this will work INSIDE the loop.
  561. *
  562. * (1) NB !!!!! is_pre is defaulted to ZERO. This means that groups
  563. * or motifs which CANNOT BE pre- or post- are defaulted to
  564. * post (which means the groups start on the tset notes, rather
  565. * leading up to them).
  566. */
  567. int space_gpnote(noteptr thisnote,int gpsize,dataptr dz)
  568. {
  569. int exit_status;
  570. if(dz->iparam[TEX_GPSPACE]==IS_SCATTER) {
  571. if((exit_status = sp_scatter(thisnote,dz))<0)
  572. return(exit_status);
  573. } else {
  574. if(dz->vflag[IS_PRE]) { /* 1 */
  575. if((exit_status = pre_place(thisnote,gpsize,dz))<0)
  576. return(exit_status);
  577. } else {
  578. if((exit_status = post_place(thisnote,gpsize,dz))<0)
  579. return(exit_status);
  580. }
  581. }
  582. dz->iparam[SPINIT] = 0; /* disable initialisation after first call to group */
  583. return(FINISHED);
  584. }
  585. /**************************** SP_SCATTER *************************
  586. *
  587. * scatter group note around position of main event.
  588. */
  589. int sp_scatter(noteptr mnote,dataptr dz)
  590. {
  591. int exit_status;
  592. double sptop = 1.0, spbot= 0.0, hfthissprange,val;
  593. if(dz->param[THISSPRANGE]<=0.0) {
  594. mnote->spacepos = (float)dz->param[TPOSITION];
  595. return(FINISHED);
  596. }
  597. if(dz->iparam[SPINIT]) {
  598. hfthissprange = dz->param[THISSPRANGE]/(double)2.0;
  599. spbot = max((dz->param[TPOSITION] - hfthissprange),0.0);
  600. sptop = min((dz->param[TPOSITION] + hfthissprange),1.0);
  601. dz->param[THISSPRANGE] = sptop - spbot;
  602. }
  603. if((exit_status = pscatx(dz->param[THISSPRANGE],spbot,PM_GPSPAC,&val,dz))<0)
  604. return(exit_status);
  605. mnote->spacepos = (float)val;
  606. return(FINISHED);
  607. }
  608. /************** MACROS FOR RANGE REORIENTATIONS AND TRUNCATIONS **************
  609. *
  610. * r = group spatial range p = position of event
  611. * c = centre of motion d = direction of motion
  612. *
  613. * (1) If position to left of centre, reverse range.
  614. * (2) If position to right of centre, reverse range.
  615. * (3) If no motion, zero the range.
  616. * (4) If motion is right to left reverse range.
  617. * (5) If motion is left to right reverse range.
  618. * (6) avoid centre crossing
  619. * (7) avoid right-edge crossing
  620. * (8) avoid left-edge crossing
  621. * (9) avoid edge crossing
  622. */
  623. #define TURNOUTWARD(r,p,c) if((p)-(c)<0.0) (r) = -(r); /* 1 */
  624. #define TURNINWARD(r,p,c) if((p)-(c)>0.0) (r) = -(r); /* 2 */
  625. #define CHECKSTIL(r,d) if((d)==0) (r) = 0.0; /* 3 */
  626. #define FOLLOW(r,d) CHECKSTIL(r,d) else { if((d)<0) (r) = -(r); } /* 4 */
  627. #define CONTRARY(r,d) CHECKSTIL(r,d) else { if((d)>0) (r) = -(r); } /* 5 */
  628. #define SET_PRE_INRANGE(r,p,c) if(p<c) r = min(p,r); else r = max(p-1.0,r);
  629. #define FREECENTRE(r,p,c) if((r)>fabs((p)-(c))) (r)=fabs((p)-(c)); /* 6 */
  630. #define FREEREDGE(r,p) if((p)+(r)>1.0) (r) = 1.0 - (p); /* 7 */
  631. #define FREELEDGE(r,p) if((p)+(r)<0.0) (r) = -(p); /* 8 */
  632. #define FREEEDGES(r,p) if((r)>=0.0) { FREEREDGE((r),(p)) } else { FREELEDGE((r),(p)) }
  633. /* 9 */
  634. #define FREEREDGE_PRE(r,p) if((p)-(r)>1.0) (r) = (p) - 1.0; /* 7 */
  635. #define FREELEDGE_PRE(r,p) if((p)-(r)<0.0) (r) = (p); /* 8 */
  636. #define FREEEDGES_PRE(r,p) if((r)>=0.0) { FREELEDGE_PRE((r),(p)) } else { FREEREDGE_PRE((r),(p)) }
  637. /* 9 */
  638. /************************* PRE_PLACE *****************************
  639. *
  640. * place-in-space ornaments or decorations BEFORE notes, or motifs or groups
  641. * at texture points.
  642. *
  643. * is_pre = 1.
  644. */
  645. int pre_place(noteptr thisnote,int gpsize,dataptr dz)
  646. {
  647. if(dz->iparam[SPINIT])
  648. dz->iparam[SPCNT] = 0;
  649. switch(dz->iparam[TEX_GPSPACE]) {
  650. case(IS_STILL):
  651. dz->param[THISSPRANGE] = 0.0;
  652. break;
  653. case(IS_INWARD):
  654. if(dz->iparam[SPINIT]) {
  655. TURNINWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  656. SET_PRE_INRANGE(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  657. }
  658. break;
  659. case(IS_OUTWARD):
  660. if(dz->iparam[SPINIT]) {
  661. FREECENTRE(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  662. TURNOUTWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  663. }
  664. break;
  665. case(IS_FOLLOWING):
  666. if(dz->iparam[SPINIT]) {
  667. FOLLOW(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
  668. FREEEDGES_PRE(dz->param[THISSPRANGE],dz->param[TPOSITION])
  669. }
  670. break;
  671. case(IS_CONTRARY):
  672. if(dz->iparam[SPINIT]) {
  673. CONTRARY(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
  674. FREEEDGES_PRE(dz->param[THISSPRANGE],dz->param[TPOSITION])
  675. }
  676. break;
  677. default:
  678. sprintf(errstr,"TEXTURE: Invalid space-type %d in pre_place()\n",dz->iparam[TEX_GPSPACE]);
  679. return(PROGRAM_ERROR);
  680. }
  681. thisnote->spacepos = (float)(dz->param[TPOSITION] - dz->param[THISSPRANGE]
  682. + ((dz->param[THISSPRANGE]/(double)gpsize)*(double)(dz->iparam[SPCNT])));
  683. dz->iparam[SPCNT]++;
  684. return(FINISHED);
  685. }
  686. /************************* POST_PLACE *****************************
  687. *
  688. * place-in-space ornaments or decorations AFTER notes, or motifs or groups
  689. * at texture points.
  690. *
  691. * is_pre = 0, (or no ornament).
  692. */
  693. int post_place(noteptr thisnote,int gpsize,dataptr dz)
  694. {
  695. if(dz->iparam[SPINIT])
  696. dz->iparam[SPCNT] = 1;
  697. switch(dz->iparam[TEX_GPSPACE]) {
  698. case(IS_STILL):
  699. dz->param[THISSPRANGE] = 0.0;
  700. break;
  701. case(IS_INWARD):
  702. if(dz->iparam[SPINIT]) {
  703. FREECENTRE(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  704. TURNINWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  705. }
  706. break;
  707. case(IS_OUTWARD):
  708. if(dz->iparam[SPINIT]) {
  709. TURNOUTWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
  710. FREEEDGES(dz->param[THISSPRANGE],dz->param[TPOSITION])
  711. }
  712. break;
  713. case(IS_FOLLOWING):
  714. if(dz->iparam[SPINIT]) {
  715. FOLLOW(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
  716. FREEEDGES(dz->param[THISSPRANGE],dz->param[TPOSITION])
  717. }
  718. break;
  719. case(IS_CONTRARY):
  720. if(dz->iparam[SPINIT]) {
  721. CONTRARY(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
  722. FREEEDGES(dz->param[THISSPRANGE],dz->param[TPOSITION])
  723. }
  724. break;
  725. default:
  726. sprintf(errstr,"TEXTURE: Invalid space-type %d in post_place()\n",dz->iparam[TEX_GPSPACE]);
  727. return(PROGRAM_ERROR);
  728. }
  729. thisnote->spacepos = (float)(dz->param[TPOSITION] +
  730. ((dz->param[THISSPRANGE]/(double)gpsize)*(double)(dz->iparam[SPCNT])));
  731. dz->iparam[SPCNT]++;
  732. return(FINISHED);
  733. }
  734. /************************** GPSP_INIT ***********************************
  735. *
  736. * Initialise the space-param for each group, before calling the spatialise
  737. * routines. 'spinit' causes initialisation of range etc elsewhere (in
  738. * pre_place() or post_place() ).
  739. */
  740. int init_group_spatialisation(noteptr tsetnote,int shaddoindex,noteptr *shadow,int shadowsize,dataptr dz)
  741. {
  742. int exit_status;
  743. dz->iparam[SPINIT] = 1;
  744. dz->param[TPOSITION] = tsetnote->spacepos;
  745. dz->param[CPOS] = tsetnote->motioncentre;
  746. if(dz->brksize[TEX_GRPSPRANGE]) { /* TABLE VALUES MUST BE 0 - 1 */
  747. if((exit_status = read_value_from_brktable((double)tsetnote->ntime,TEX_GRPSPRANGE,dz))<0)
  748. return(exit_status);
  749. }
  750. if(IS_DIRECTED(dz->iparam[TEX_GPSPACE]))
  751. dz->iparam[DIRECTION] = read_direction(shaddoindex,shadow,shadowsize);
  752. dz->param[THISSPRANGE] = dz->param[TEX_GRPSPRANGE];
  753. return(FINISHED);
  754. }
  755. /**************************** READ_DIRECTION ****************************
  756. *
  757. * Read direction of motion from spatial position stored in note.
  758. *
  759. * NB: as the tset is in the process of being modified, we cannot
  760. * refer directly to the tset linked list. We can only access the original
  761. * tset through it's 'shadow'.
  762. *
  763. * (0) Save the time of the current note as 'now'.
  764. * (1) Save position of current note as 'here'.
  765. * (2) Whilever we're not at the end of the tset (shadow).
  766. * (a) Note time of next note, store as 'then'.
  767. * (b) If 'then' is later than 'now'.
  768. * Note position of new note as 'there'.
  769. * Set as OK and break out of loop.
  770. * (3) If it's not OK (i.e. we were at, or came to the end of the tset
  771. * (shadow))....
  772. * (a) Go back to where we started.
  773. * (b) Call this position 'there'.
  774. * (4) While ever we're not at beginning of tset...
  775. * (a) Note time of previous note, store as 'then'.
  776. * (b) If 'then' is 'earlier' than 'now'...
  777. * Note position of new note as 'here'.
  778. * Set as OK and break out of loop.
  779. * (5) If still not OK, then there is no more than 1 (non-simultaneous)
  780. * event in the tset, so therefore no motion, so return 0.
  781. * (6) If there>here, left-to-right motion, return 1.
  782. * (7) If here>there, right-to-left motion, return -1.
  783. * (8) Otherwise, no motion, return 0.
  784. */
  785. int read_direction(int shi,noteptr *shadow,int shadowsize)
  786. {
  787. unsigned char OK;
  788. float here, there = 0.0;
  789. double now, then;
  790. int startshi = shi;
  791. now = (shadow[shi])->ntime; /* 0 */
  792. here = (shadow[shi])->motioncentre; /* 1 */
  793. OK = 0;
  794. while(++shi<shadowsize) { /* 2 */
  795. then = (shadow[shi])->ntime; /* a */
  796. if(then>(now+FLTERR)) { /* b */
  797. there = (shadow[shi])->motioncentre;
  798. OK = 1;
  799. break;
  800. }
  801. }
  802. if(!OK) { /* 3 */
  803. shi = startshi; /* a */
  804. there = here; /* b */
  805. while(--shi>=0) { /* 4 */
  806. then = (shadow[shi])->ntime; /* a */
  807. if(then<(now-FLTERR)) { /* b */
  808. here = (shadow[shi])->motioncentre;
  809. OK = 1;
  810. break;
  811. }
  812. }
  813. }
  814. if(!OK)
  815. return(0); /* 5 */
  816. if(there>here) /* 6 */
  817. return(1);
  818. if(there<here) /* 7 */
  819. return(-1);
  820. return(0); /* 8 */
  821. }
  822. /*************************** GETAMPSTEP ******************************
  823. *
  824. * Select flat, cresc or decresc, from available types.
  825. *
  826. * (1) IF the cresc will be from zero, clrzamp is 1, and this makes
  827. * the amplitude steps a little smaller, so that 1st note in sequence
  828. * will not be at amplitude zero.
  829. * OTHERWISE, clrzamp = 0, and ampstep is as normal.
  830. */
  831. int getampstep
  832. (double *ampstep,double amp,unsigned char *amptype,int gpsize,unsigned char amptypecnt,
  833. unsigned char amptypestor,dataptr dz)
  834. {
  835. int exit_status;
  836. int clrzamp = 0, k;
  837. /*int texflag = dz->tex->txflag;*/
  838. if((exit_status = doperm((int)amptypecnt,PM_GPCNTR,&k,dz))<0)
  839. return(exit_status);
  840. if((exit_status = gettritype(k,amptypestor,amptype))<0)
  841. return(exit_status);
  842. if(*amptype==FLAT) /**** FLAT *****/
  843. *ampstep =0.0;
  844. else {
  845. *ampstep = dz->param[TEX_AMPRISE]; /* param with <|> option */
  846. if(*ampstep>=amp) {
  847. clrzamp = 1;
  848. *ampstep = amp;
  849. }
  850. *ampstep /= (double)(gpsize + clrzamp); /* 1 */
  851. if(*amptype==DECRESC) /** DECRESCENDO **/
  852. *ampstep = -(*ampstep);
  853. }
  854. return(FINISHED);
  855. }
  856. /*************************** GETDIRAMPSTEP ******************************
  857. *
  858. * (1) If there are two amplitude types, in THIS CASE, these can only
  859. * be DIRECTED or FLAT. So...
  860. * (2) Choose flat or directed via perm.
  861. * (3) and if it's flat, return an ampstep of zero.
  862. * Otherwise, we proceed as in the normal case of a directed amp.
  863. * (4) Set initial ampstep to amprise.
  864. * (5) IF the cresc will be from zero, or decresc to zero, clrzamp is 1,
  865. * and this makes the amplitude steps a little smaller, so that 1st note
  866. * of cresc (or last note of decresc) will not be at amplitude zero.
  867. * OTHERWISE, clrzamp = 0, and ampstep is as normal.
  868. * (6) Divide ampstep by number of members in group.
  869. * (7) If it's a post-ornament, ampstep is negative.
  870. */
  871. int getdirampstep
  872. (double amp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz)
  873. {
  874. int exit_status;
  875. int k, clrzamp = 0;
  876. if(amptypecnt==2) { /* 1 */
  877. if((exit_status= doperm((int)2,PM_GPCNTR,&k,dz))<0) /* 2 */
  878. return(exit_status);
  879. if(k==0) {
  880. *ampstep = 0.0;
  881. return(FINISHED); /* 3 */
  882. }
  883. }
  884. *ampstep = dz->param[TEX_AMPRISE]; /* param with <|> option */ /* 4 */
  885. if(*ampstep>=amp) { /* 5 */
  886. clrzamp = 1;
  887. *ampstep = amp;
  888. }
  889. *ampstep /= (double)(gpsize + clrzamp); /* 6 */
  890. if(!dz->vflag[IS_PRE]) /* 7 */
  891. *ampstep = -(*ampstep);
  892. return(FINISHED);
  893. }
  894. /*************************** GETMTFDIRAMPSTEP *******************************
  895. *
  896. * Intelligent guesswork!! Nov 4: 1997
  897. */
  898. int getmtfdirampstep(double amp,double framp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz)
  899. {
  900. int exit_status;
  901. int k, clrzamp = 0;
  902. if(amptypecnt==2) { /* 1 */
  903. if((exit_status= doperm((int)2,PM_GPCNTR,&k,dz))<0) /* 2 */
  904. return(exit_status);
  905. if(k==0) {
  906. *ampstep = 0.0;
  907. return(FINISHED); /* 3 */
  908. }
  909. }
  910. if(amp>(dz->param[TEX_AMPRISE] + framp))
  911. *ampstep = dz->param[TEX_AMPRISE];
  912. else {
  913. *ampstep = amp - framp;
  914. clrzamp = 1;
  915. }
  916. *ampstep /= (double)(gpsize + clrzamp); /* 6 */
  917. if(!dz->vflag[IS_PRE]) /* 7 */
  918. *ampstep = -(*ampstep);
  919. return(FINISHED);
  920. }
  921. /************************* GET_DEC_OR_ORN_POS ***************************
  922. *
  923. * Decuptype flags are selected and shifted down into the range 0-3
  924. * If its 01 (1), it's a post-ornament, so set 'is_pre' = FALSE.
  925. * If its 10 (2), it's a pre_ornament, so set 'is_pre' = TRUE
  926. * If its 00 (0), it's not set, so we select 'is_pre' at random using doperm on 2 (output 0S or 1).
  927. *
  928. * NB: If we are using a group or motif, rather than a decoration
  929. * or ornament, is_pre is BY DEFAULT set to 0.
  930. */
  931. int get_dec_or_orn_pos(dataptr dz)
  932. {
  933. int exit_status;
  934. int k;
  935. unsigned int dectype = dz->tex->txflag & GET_DECORNPOS;
  936. switch(dectype) {
  937. case(1): dz->vflag[IS_PRE] = TRUE; break;
  938. case(2): dz->vflag[IS_PRE] = FALSE; break;
  939. default:
  940. if((exit_status = doperm((int)2,PM_ORNPOS,&k,dz))<0)
  941. return(exit_status);
  942. dz->vflag[IS_PRE] = (char)k;
  943. break;
  944. }
  945. if(dz->vflag[IS_PRE] > 1) {
  946. sprintf(errstr,"Error from perm in get_dec_or_orn_pos()\n");
  947. return(PROGRAM_ERROR);
  948. }
  949. return(FINISHED);
  950. }
  951. /**************************** SUBZERO ***********************************
  952. *
  953. * If start of a decoration falls before time zero, adjust its size
  954. * and hence starttime(-minus-gpdense) appropriately.
  955. */
  956. int subzero(double *thistime,double gpdense,int *gpsize)
  957. {
  958. int n = -1;
  959. while(*thistime>=0.0) {
  960. *thistime -= gpdense;
  961. n++;
  962. }
  963. if(n<0) {
  964. sprintf(errstr,"TEXTURE: Problem in subzero()\n");
  965. return(PROGRAM_ERROR);
  966. }
  967. *gpsize = n;
  968. return(FINISHED);
  969. }
  970. /*************************** GETHIPITCH *********************************#
  971. *
  972. * Find highest pitch at current time.
  973. */
  974. noteptr gethipitch(noteptr tsetnote,int *shaddoindex)
  975. {
  976. noteptr hinote, thisnote;
  977. double hipitch;
  978. int zz = *shaddoindex;
  979. hinote = thisnote = tsetnote;
  980. hipitch = (double)hinote->pitch;
  981. while(thisnote->next!=(noteptr)0) {
  982. if(thisnote->next->ntime > thisnote->ntime + FLTERR)
  983. return(hinote);
  984. thisnote = thisnote->next;
  985. zz++;
  986. if((double)thisnote->pitch > hipitch) {
  987. hipitch = (double)thisnote->pitch;
  988. hinote = thisnote;
  989. (*shaddoindex) = zz;
  990. }
  991. }
  992. return(hinote);
  993. }
  994. /****************************** DO_GRP_INS **********************************
  995. *
  996. * Choose instr-no within group/decoration/motif or ornament.
  997. * Values of instr-no range are preset when instr is chosen for the
  998. * tset, in do_ev_ins().
  999. */
  1000. int do_grp_ins(unsigned char thisinstr,unsigned char *val,dataptr dz)
  1001. {
  1002. int exit_status;
  1003. int irange, ival;
  1004. if(dz->vflag[INS_TO_SCATTER]) {
  1005. if((irange = (int)(dz->iparam[TEXTURE_INSHI] - dz->iparam[TEXTURE_INSLO])) < 0) {
  1006. iswap((int *)&(dz->iparam[TEXTURE_INSHI]),(int *)&(dz->iparam[TEXTURE_INSLO]));
  1007. irange = -irange;
  1008. }
  1009. if(irange==0)
  1010. *val = (unsigned char)dz->iparam[TEXTURE_INSLO];
  1011. else {
  1012. if((exit_status = doperm(irange+1,PM_INSNO,&ival,dz))<0) /* range INCLUSIVE for ints */
  1013. return(exit_status);
  1014. *val = (unsigned char)(ival + dz->iparam[TEXTURE_INSLO]);
  1015. }
  1016. } else
  1017. *val = thisinstr;
  1018. return(FINISHED);
  1019. }
  1020. /***************************** PSCATX ************************************
  1021. *
  1022. * Select a random value within 'range', by permuting one of BANDCNT equal
  1023. * ranges, and selecting a random value within the chosen range.
  1024. */
  1025. int pscatx(double range,double bottom,int pindex,double *val,dataptr dz)
  1026. {
  1027. int k, exit_status;
  1028. double bandwidth, bandbottom, x;
  1029. if((exit_status = doperm((int)BANDCNT,pindex,&k,dz))<0)
  1030. return(exit_status);
  1031. bandwidth = range/(double)BANDCNT;
  1032. bandbottom = (double)k * bandwidth;
  1033. x = (drand48() * bandwidth);
  1034. x += bandbottom;
  1035. *val = x + bottom;
  1036. return(FINISHED);
  1037. }
  1038. /*************************** DEL_NOTE ************************************/
  1039. void del_note(noteptr thisnote,motifptr thismotif)
  1040. {
  1041. if(thisnote->next!=(noteptr)0)
  1042. thisnote->next->last = thisnote->last; /* 1 */
  1043. if(thisnote->last!=(noteptr)0)
  1044. thisnote->last->next = thisnote->next; /* 2 */
  1045. else
  1046. thismotif->firstnote = thisnote->next; /* 3 */
  1047. free(thisnote); /* 4 */
  1048. }
  1049. /************************** TIMESORT ****************************
  1050. *
  1051. * Timesorts notes in a list
  1052. *
  1053. * (1) Move the item with earliest time to start of list, and set this
  1054. * (minimum) time as maximum time also.
  1055. * For each item in the list....
  1056. * (2) If this item is earlier than current latest item (maxtime)..
  1057. * (3) Find where it should be in the list.
  1058. * (4) move it to that location.
  1059. * (5) Otherwise, set this item's time as latest time(maxtime).
  1060. * (6) Reset motifhead to start of notelist!!
  1061. */
  1062. int arrange_notes_in_timeorder(motifptr mtf)
  1063. {
  1064. noteptr base, here, there, mark;
  1065. double thistime, maxtime;
  1066. if((base = mtf->firstnote)==(noteptr)0)
  1067. return(FINISHED);
  1068. maxtime = setup_first_notelist_time(&base); /* 1 */
  1069. here = base;
  1070. while(here!=(noteptr)0) {
  1071. if((thistime = here->ntime) < maxtime) { /* 2 */
  1072. if((mark = here->last)==(noteptr)0) {
  1073. sprintf(errstr,"Problem (1) in arrange_notes_in_timeorder()\n");
  1074. return(PROGRAM_ERROR);
  1075. }
  1076. if((there = reverse_search_for_time(here,thistime))==(noteptr)0) {
  1077. sprintf(errstr,"Timing problem in arrange_notes_in_timeorder()\n");
  1078. return(PROGRAM_ERROR);
  1079. } /* 3 */
  1080. move_notelist_item(here,there); /* 4 */
  1081. here = mark;
  1082. } else
  1083. maxtime = here->ntime; /* 5 */
  1084. here = here->next;
  1085. }
  1086. return reset_mtfhead(mtf); /* 6 */
  1087. }
  1088. /************************* RESET_MTFHEAD ***************************
  1089. *
  1090. * Reset pointer to start of notelist.
  1091. */
  1092. int reset_mtfhead(motifptr mtf)
  1093. {
  1094. noteptr here = mtf->firstnote;
  1095. if(mtf->firstnote==NULL) {
  1096. sprintf(errstr,"Problem in reset_mrfhead()\n");
  1097. return(PROGRAM_ERROR);
  1098. }
  1099. while(here->last!=(noteptr)0)
  1100. here = here->last;
  1101. mtf->firstnote = here;
  1102. return(FINISHED);
  1103. }
  1104. /************************** SETUP_FIRST_NOTELIST_TIME ***************************
  1105. *
  1106. * Put the earliest timed item in a list of notes into start of list.
  1107. */
  1108. double setup_first_notelist_time(noteptr *base)
  1109. {
  1110. noteptr firstnote, here;
  1111. double mintime, thistime;
  1112. firstnote = here = *base;
  1113. mintime = (*base)->ntime;
  1114. while(here!=(noteptr)0) {
  1115. if((thistime = here->ntime)<mintime) {
  1116. firstnote = here;
  1117. mintime = thistime;
  1118. }
  1119. here = here->next;
  1120. }
  1121. if(firstnote!=(*base)) {
  1122. move_notelist_item(firstnote,(*base));
  1123. *base = firstnote;
  1124. }
  1125. return(mintime);
  1126. }
  1127. /************************* MOVE_NOTELIST_ITEM ***************************
  1128. *
  1129. * Move an item in a notelist from location a to BEFORE location b.
  1130. */
  1131. void move_notelist_item(noteptr a,noteptr b)
  1132. {
  1133. if(a->last!=(noteptr)0)
  1134. a->last->next = a->next;
  1135. if(a->next!=(noteptr)0)
  1136. a->next->last = a->last;
  1137. a->next = b;
  1138. a->last = b->last;
  1139. if(b->last!=(noteptr)0)
  1140. b->last->next = a;
  1141. b->last = a;
  1142. }
  1143. /************************** REVERSE_SEARCH_FOR_TIME *****************************
  1144. *
  1145. * Reverse search note-list using a time as index, and return address
  1146. * of note whose time is AFTER the input time.
  1147. * WILL RETURN (noteptr)0 IF REFTIME IS OFF END OF LIST.
  1148. */
  1149. noteptr reverse_search_for_time(noteptr start,double reftime)
  1150. {
  1151. noteptr here = start;
  1152. while(here->ntime >= reftime) {
  1153. if(here->last == (noteptr)0)
  1154. return(here);
  1155. here = here->last;
  1156. }
  1157. return(here->next);
  1158. }
  1159. /************************** ISWAP *****************************/
  1160. void iswap(int *a,int *b)
  1161. {
  1162. int temp;
  1163. temp = *a;
  1164. *a = *b;
  1165. *b = temp;
  1166. }
  1167. /****************************** SET_GROUP_PARAMS **********************************/
  1168. int set_group_params
  1169. (noteptr tsetnote,noteptr thisnote,double gpdense,double ampstep,double *thisamp,double *thistime,double thisdur,dataptr dz)
  1170. {
  1171. int exit_status;
  1172. double thisgpdense, time_left;
  1173. *thisamp += ampstep;
  1174. thisnote->amp = (float)*thisamp;
  1175. thisnote->dur = (float)thisdur;
  1176. if(dz->vflag[FIXED_STEP])
  1177. *thistime += gpdense;
  1178. else {
  1179. if((exit_status = get_density_val(*thistime,&thisgpdense,dz))<0)
  1180. return(exit_status);
  1181. if((dz->tex->txflag & IS_DECOR) && dz->vflag[IS_PRE]) {
  1182. if((time_left = tsetnote->ntime - *thistime)<0.0) {
  1183. sprintf(errstr,"Error in assumptions: set_group_params()\n");
  1184. return(PROGRAM_ERROR);
  1185. }
  1186. time_left *= 0.66;
  1187. thisgpdense = min(time_left,thisgpdense);
  1188. }
  1189. *thistime += thisgpdense;
  1190. }
  1191. return(FINISHED);
  1192. }
  1193. /***************************** GETTRITYPE *****************************
  1194. *
  1195. * Choose a type, from up to three available types in bit-flag.
  1196. * e.g.
  1197. * Choose an amplitude type (flat,cresc,decresc) from 3 available types.
  1198. * Choose a decoration-orientation type (above,below,mid) from 3 types.
  1199. *
  1200. * (1) For each type in the bitflag.
  1201. * (2) If this option is flagged, count it.
  1202. * (3) IF this option is chosen, return its bit-number.
  1203. * (4) Advance the bitflag mask.
  1204. */
  1205. int gettritype(int k,unsigned stor,unsigned char *val)
  1206. {
  1207. int v = 0, mask = 1, n;
  1208. k++;
  1209. for(n=0;n<3;n++) { /* 1 */
  1210. if(mask & stor) /* 2 */
  1211. v++;
  1212. if(k==v) { /* 3 */
  1213. *val = (unsigned char)n;
  1214. return(FINISHED);
  1215. }
  1216. mask <<= 1; /* 4 */
  1217. }
  1218. sprintf(errstr,"TEXTURE: Problem in gettritype()\n");
  1219. return(PROGRAM_ERROR);
  1220. }
  1221. /*************************** GET_DENSITY_VAL ******************************/
  1222. int get_density_val(double thistime,double *gpdense,dataptr dz)
  1223. {
  1224. int exit_status;
  1225. if((exit_status = getvalue(TEX_GPPACKHI,TEX_GPPACKLO,thistime,PM_GPDENS,gpdense,dz))<0)
  1226. return(PROGRAM_ERROR);
  1227. /* NEW MAR 2000 */
  1228. *gpdense *= MS_TO_SECS;
  1229. if(dz->param[TEX_PHGRID]>0.0)
  1230. *gpdense = quantise(*gpdense,dz->param[TEX_PHGRID]);
  1231. return FINISHED;
  1232. }
  1233. /**************************** SET_MOTIFS *******************************
  1234. *
  1235. * initialise all parameters of input motifs to be used for MOTIFS or
  1236. * ORNAMENTS.
  1237. *
  1238. * (1)For each input motif (called a 'phrase').
  1239. * phrnotecnt[n] = 0;
  1240. * (2) Initialise count of number of notes to 0, maximum amplitude
  1241. * of phrase to 0.0, and lowest pitch to MIDITOP.
  1242. * (3) Go through each note of the motif.
  1243. * (4) Add up the number of notes in it.
  1244. * (5) Find it's lowest pitch.
  1245. * (6) Find it's loudest note (and set as phraseamp).
  1246. * (7) Establish dynamic range of phrase.
  1247. * (8) Transpose the motif into it's lowest possible register.
  1248. * (9) Ensure motif starts at zero time.
  1249. * (10) Store addresses of last notes in phrases.
  1250. */
  1251. int set_motifs
  1252. (int phrcount,motifptr *phrase,int *phrnotecnt,double *phraseamp,double *phrange,noteptr *phrlastnote)
  1253. {
  1254. int exit_status;
  1255. int n;
  1256. double minpitch, mintime, minamp;
  1257. noteptr thisnote, lastnote = (noteptr)0;
  1258. for(n=0;n<phrcount;n++) { /* 1 */
  1259. if((exit_status = arrange_notes_in_timeorder(phrase[n]))<0)
  1260. return(exit_status);
  1261. phrnotecnt[n] = 0;
  1262. phraseamp[n] = 0.0; /* 2 */
  1263. minamp = DBL_MAX;
  1264. minpitch = MIDITOP;
  1265. mintime = DBL_MAX;
  1266. thisnote = phrase[n]->firstnote; /* 3 */
  1267. while(thisnote!=(noteptr)0) {
  1268. phrnotecnt[n]++; /* 4 */
  1269. if(thisnote->pitch<minpitch)
  1270. minpitch = thisnote->pitch; /* 5 */
  1271. if(thisnote->ntime<mintime)
  1272. mintime = thisnote->ntime; /* 5 */
  1273. if((double)thisnote->amp>phraseamp[n])
  1274. phraseamp[n] = (double)thisnote->amp;/* 6 */
  1275. if(thisnote->amp<minamp)
  1276. minamp = thisnote->amp; /* 6 */
  1277. thisnote = thisnote->next;
  1278. }
  1279. if(minamp == DBL_MAX || mintime == DBL_MAX) {
  1280. sprintf(errstr,"Error parsing motif: set_motifs()\n");
  1281. return(PROGRAM_ERROR);
  1282. }
  1283. thisnote = phrase[n]->firstnote;
  1284. phrange[n] = phraseamp[n] - minamp; /* 7 */
  1285. while(thisnote!=(noteptr)0) {
  1286. thisnote->pitch = (float)(thisnote->pitch - (minpitch + MIDIBOT)); /* 8 */
  1287. thisnote->ntime = (float)(thisnote->ntime - mintime); /* 9 */
  1288. lastnote = thisnote; /* 10 */
  1289. thisnote = thisnote->next;
  1290. }
  1291. if((phrlastnote[n] = lastnote) == (noteptr)0) {
  1292. sprintf(errstr,"Zero length phrase encountered: set_motifs()\n");
  1293. return(PROGRAM_ERROR);
  1294. }
  1295. }
  1296. return(FINISHED);
  1297. }
  1298. void cyclicperm(dataptr dz)
  1299. {
  1300. int n, t;
  1301. do {
  1302. for(n=0;n<dz->infilecnt;n++) {
  1303. t = (int)floor(drand48() * (n+1));
  1304. if(t==n) {
  1305. hprefix(n,dz->peakno,dz->infilecnt);
  1306. } else {
  1307. hinsert(n,t,dz->peakno,dz->infilecnt);
  1308. }
  1309. }
  1310. } while(dz->peakno[0] == dz->lastpeakno[dz->infilecnt - 1]); // Avoid repetitions at perm boundaries.
  1311. for(n=0;n<dz->infilecnt;n++)
  1312. dz->lastpeakno[n] = dz->peakno[n];
  1313. }
  1314. void hinsert(int m,int t,int *perm,int permlen)
  1315. {
  1316. hshuflup(t+1,perm,permlen);
  1317. perm[t+1] = m;
  1318. }
  1319. void hprefix(int m,int *perm,int permlen)
  1320. {
  1321. hshuflup(0,perm,permlen);
  1322. perm[0] = m;
  1323. }
  1324. void hshuflup(int k,int *perm,int permlen)
  1325. {
  1326. int n, *i;
  1327. int z = permlen - 1;
  1328. i = perm+z;
  1329. for(n = z;n > k;n--) {
  1330. *i = *(i-1);
  1331. i--;
  1332. }
  1333. }
  1334. //RWD OCT 2025 no longer needed
  1335. #if 0
  1336. # ifndef round
  1337. int round(double a)
  1338. {
  1339. return (int)floor(a + 0.5);
  1340. }
  1341. # endif
  1342. #endif