| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474 |
- /*
- * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
- * http://www.trevorwishart.co.uk
- * http://www.composersdesktop.com
- *
- This file is part of the CDP System.
-
- The CDP System is free software; you can redistribute it
- and/or modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The CDP System is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the CDP System; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
- *
- */
- /* floatsam version : no changes */
- #include <stdio.h>
- #include <stdlib.h>
- #include <float.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <globcon.h>
- #include <processno.h>
- #include <modeno.h>
- #include <arrays.h>
- #include <texture.h>
- #include <cdpmain.h>
- #include <sfsys.h>
- #include <osbind.h>
- #if defined unix || defined __GNUC__
- #define round(x) lround((x))
- #endif
- /**** ALL FUNCTIONS WHICH ARE GLOBAL TO ALL PROCESS FUNCTIONS TYPES ***/
- /* Functions which are global to all texture applications.
- */
- static void orn_subzero(double *thistime,noteptr phrlastnote,noteptr *phrasenote,
- double *timeadjust,double multiplier,int *gpsize);
- static int getmtfampstep
- (double amp,double framp,double *ampstep,unsigned char *amptype,
- unsigned char amptypestor,unsigned char amptypecnt,int gpsize,dataptr dz);
- static int space_gpnote(noteptr thisnote,int gpsize,dataptr dz);
- static int sp_scatter(noteptr mnote,dataptr dz);
- static int pre_place(noteptr thisnote,int gpsize,dataptr dz);
- static int post_place(noteptr thisnote,int gpsize,dataptr dz);
- static int read_direction(int shi,noteptr *shadow,int shadowsize);
- static int do_ev_ins(unsigned char *thisinstr,double thistime,dataptr dz);
- static int do_ev_amp(double *thisamp,double thistime,dataptr dz);
- static int do_ev_dur(double *thisdur,double thistime,dataptr dz);
- static int getdirampstep
- (double amp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz);
- static int getampstep
- (double *ampstep,double amp,unsigned char *amptype,int gpsize,unsigned char amptypecnt,
- unsigned char amptypestor,dataptr dz);
- static int get_dec_or_orn_pos(dataptr dz);
-
- static int subzero(double *thistime,double gpdense,int *gpsize);
- static noteptr reverse_search_for_time(noteptr start,double reftime);
- static void move_notelist_item(noteptr a,noteptr b);
- static double setup_first_notelist_time(noteptr *base);
- static int reset_mtfhead(motifptr mtf);
- static int post_place(noteptr thisnote,int gpsize,dataptr dz);
- static int getmtfdirampstep
- (double amp,double framp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz);
- static void cyclicperm(dataptr dz);
- static void hinsert(int m,int t,int *perm,int permlen);
- static void hprefix(int m,int *perm,int permlen);
- static void hshuflup(int k,int *perm,int permlen);
- /***************************** OCTADJUST *****************************
- *
- * Check for range overflow of pitch.
- */
- double octadjust(double thispitch)
- {
- if(thispitch>MIDITOP)
- thispitch -= SEMITONES_PER_OCTAVE;
- if(thispitch<MIDIBOT)
- thispitch += SEMITONES_PER_OCTAVE;
- return(thispitch);
- }
- /***************************** DO_AMP_INSTR_DUR ************************************/
- int do_amp_instr_dur
- (double *thisamp,unsigned char *thisinstr,double *thisdur,noteptr tsetnote,double thistime,dataptr dz)
- {
- int exit_status;
- if((exit_status = do_ev_amp(thisamp,thistime,dz))<0)
- return(exit_status);
- tsetnote->amp = (float)(*thisamp);
- if((exit_status = do_ev_ins(thisinstr,thistime,dz))<0)
- return(exit_status);
- tsetnote->instr = *thisinstr;
- if((exit_status = do_ev_dur(thisdur,thistime,dz))<0)
- return(exit_status);
- tsetnote->dur = (float)(*thisdur);
- return(FINISHED);
- }
- /********************** DO_EV_INS *******************************
- *
- * Set instrument of event (not group etc.).
- *
- * (0) If instruments in ornament or decoration are to be relative to
- * input instr, return this input instrument.
- * (1) If there is a pre-existing timed set (pretimed = 1).
- * (2) Negative value causes original value to be replaced
- * by orig + abs(neg value).
- * Zero value, by default, causes orig value to be retained.
- */
- int do_ev_ins(unsigned char *thisinstr,double thistime,dataptr dz)
- {
- int exit_status;
- int instrval;
- if(dz->process == SIMPLE_TEX && dz->vflag[CYCLIC_TEXFLAG]) {
- if(dz->itemcnt == dz->infilecnt)
- dz->itemcnt = 0;
- if(dz->vflag[PERM_TEXFLAG]) {
- if(dz->itemcnt == 0)
- cyclicperm(dz);
- *thisinstr = (unsigned char)dz->peakno[dz->itemcnt];
- } else {
- *thisinstr = (unsigned char)dz->itemcnt;
- }
- dz->itemcnt++;
- } else {
- if((exit_status = igetvalue(TEXTURE_INSHI,TEXTURE_INSLO,thistime,PM_INSNO,&instrval,dz))<0)
- return(exit_status);
- *thisinstr = (unsigned char)instrval;
- }
- return(FINISHED);
- }
- /********************** DO_EV_AMP ********************************/
- int do_ev_amp(double *thisamp,double thistime,dataptr dz)
- {
- int exit_status;
- if((exit_status = getvalue(TEXTURE_MAXAMP,TEXTURE_MINAMP,thistime,PM_AMP,thisamp,dz))<0)
- return(exit_status);
- *thisamp *= dz->param[TEXTURE_ATTEN];
- if(*thisamp>MIDITOP + 0.5) {
- sprintf(errstr,"TEXTURE: amplitude [%.1f] out of midirange at time %.2f\n",*thisamp,thistime);
- return(DATA_ERROR);
- }
- return(FINISHED);
- }
- /********************** DO_EV_DUR ********************************/
- int do_ev_dur(double *thisdur,double thistime,dataptr dz)
- {
- int exit_status;
- if((exit_status = getvalue(TEXTURE_MAXDUR,TEXTURE_MINDUR,thistime,PM_DUR,thisdur,dz))<0)
- return(exit_status);
- return(FINISHED); /* 4 */
- }
- /************************ MAKE_SHADOW ****************************
- *
- * Store addresses of original tset notes.
- */
- int make_shadow(motifptr tset,int *shadowsize,noteptr **shadow)
- {
- noteptr *sh, thisnote = tset->firstnote;
- int n;
- *shadowsize = 0;
- while(thisnote!=(noteptr)0) {
- (*shadowsize)++;
- thisnote = thisnote->next;
- }
- if((sh = *shadow = (noteptr *)malloc((*shadowsize) * sizeof(noteptr)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for shadow.\n");
- return(MEMORY_ERROR);
- }
- thisnote = tset->firstnote;
- n = 0;
- while(thisnote!=(noteptr)0) {
- sh[n++] = thisnote;
- thisnote = thisnote->next;
- }
- return(FINISHED);
- }
- /************************ ERASE_SHADOW ****************************
- *
- * Erase original tset from resultant list.
- *
- * (0) Assuming shadow starts at start of tset, if first note of
- * shadow is deleted, del_note automatically resets motifptr (tset)
- * to next note (and so on).
- * (1) In case shadow started AFTER start of tset (should be impossible!!)
- * reset pointer to start of remaining motif !
- */
- int erase_shadow(int shadowsize,noteptr *shadow,motifptr tset)
- {
- int n;
- noteptr thisnote;
- for(n=0;n<shadowsize;n++) /* 0 */
- del_note(shadow[n],tset);
- if((thisnote = tset->firstnote->last)!=(noteptr)0) { /* 1 */
- sprintf(errstr,"TEXTURE: erase_shadow(): First note of shadow NOT first note of tset.\n"
- "This should never happen\n");
- return(PROGRAM_ERROR);
- /**** REMOVED FOLLOWING AUTO-CORRECTION CODE : OCT 1997 *****
- while(thisnote->last!=(noteptr)0)
- thisnote = thisnote->last;
- tset->firstnote = thisnote;
- ****/
- }
- return(FINISHED);
- }
- /************************ SETUP_DECOR ****************************/
- void setup_decor(double *pptop,double *ppbot,int *shadindex,noteptr *tsetnote,dataptr dz)
- {
- *pptop = MIDITOP;
- *ppbot = MIDIBOT;
- if(dz->vflag[WHICH_CHORDNOTE]==DECOR_HIGHEST)
- *tsetnote = gethipitch(*tsetnote,shadindex);
- }
- /**************************** SETUP_ORNAMENT *********************************/
- int setup_ornament
- (double *timeadjust,double *thistime,int *gpsize,noteptr *phrlastnote,
- double multiplier,noteptr *phrasenote,int phrno,dataptr dz)
- {
- int exit_status;
- double origtime;
- if((exit_status = get_dec_or_orn_pos(dz))<0)
- return(exit_status);
- *timeadjust = 0.0;
- if(dz->vflag[IS_PRE]) {
- origtime = *thistime;
- if((*thistime -= (phrlastnote[phrno])->ntime * multiplier)<0.0) {
- *thistime = origtime;
- orn_subzero(thistime,phrlastnote[phrno],phrasenote,timeadjust,multiplier,gpsize);
- }
- }
- return(FINISHED);
- }
- /**************************** SET_MOTIF_AMP *********************************/
- int set_motif_amp
- (noteptr tsetnote,double *thisamp,int gpsize,double ampstep,noteptr phrasenote,double rangemult,
- double *phraseamp,int phrno,unsigned char amptype)
- {
- double ampdif;
- if(amptype==CRESC) {
- *thisamp -= (double)(gpsize) * ampstep;
- ampdif = (phraseamp[phrno] - phrasenote->amp) * rangemult;
- tsetnote->amp = (float)(*thisamp - ampdif);
- }
- return(FINISHED);
- }
- /**************************** SET_ORNAMENT_AMP *********************************/
- int set_ornament_amp
- (double *phraseamp,noteptr *phrlastnote,double *thisamp,
- noteptr phrasenote,int phrno,noteptr tsetnote,
- double ampstep,double rangemult,int gpsize,dataptr dz)
- {
- double ampdif;
- if(dz->vflag[IS_PRE])
- ampdif=(phraseamp[phrno]-phrlastnote[phrno]->amp) * rangemult;
- else
- ampdif=(phraseamp[phrno]-phrasenote->amp) * rangemult;
- tsetnote->amp -= (float)ampdif;
- if(ampstep>0.0) /* CRESCENDO */
- *thisamp -= (double)(gpsize+1) * ampstep;
- return(FINISHED);
- }
- /**************************** CHECK_NEXT_PHRASENOTE_EXISTS *********************************/
- int check_next_phrasenote_exists(noteptr *phrasenote,int texflag,dataptr dz)
- {
- if(texflag & IS_MOTIFS) {
- if((*phrasenote = (*phrasenote)->next)==(noteptr)0) {
- sprintf(errstr,"TEXTURE: Accounting Problem in check_next_phrasenote_exists()\n");
- return(PROGRAM_ERROR);
- }
- } else if (texflag & IS_ORNATE){
- if(*phrasenote==(noteptr)0) {
- sprintf(errstr,"TEXTURE: 1st Accounting Problem in check_next_phrasenote_exists()\n");
- return(PROGRAM_ERROR);
- }
- if(dz->vflag[IS_PRE] && ((*phrasenote)->next==(noteptr)0)) {
- sprintf(errstr,"TEXTURE: 2nd Accounting Problem in check_next_phrasenote_exists()\n");
- return(PROGRAM_ERROR);
- }
- }
- return(CONTINUE);
- }
- /************************* GETNEXTEVENT_TO_DECORATE ***************************
- *
- * Get the next event in list, i.e. skip over simultaneous events
- * (e.g. chords).
- *
- * (0) If flagged as 2, ornaments/decorations are attached to EVERY note
- * so the next event is just the next note in the tset.
- * OTHERWISE we search for the next event AT A NEW TIME.
- * (1) If flagged, force a search for the highest note of a simultaneous
- * group (chord). Hence ornament/dec attaches to highest note.
- * Otherwise, ornament attached to first listed note of chord in input
- * data.
- */
- noteptr getnextevent_to_decorate(noteptr tsetnote,int *shaddoindex,dataptr dz)
- {
- if(dz->vflag[WHICH_CHORDNOTE]==DECOR_EVERY) /* 0 */
- return(tsetnote->next);
- while(tsetnote->next!=(noteptr)0) {
- tsetnote = tsetnote->next;
- (*shaddoindex)++;
- if(!flteq((double)tsetnote->ntime,(double)tsetnote->last->ntime)) {
- if(dz->vflag[WHICH_CHORDNOTE]==DECOR_HIGHEST)
- tsetnote = gethipitch(tsetnote,shaddoindex); /* 1 */
- return(tsetnote);
- }
- }
- return((noteptr)0);
- }
-
- /************************** GETNOTETIME ********************************
- *
- * Get actual time of note, from time of tset note, and time of motif
- * or ornament note.
- * (a) Time is set by an offset from the tset-note, THROUGHOUT each
- * motif-placement. The offset for each note is its position in the
- * original note (which have been set relative to zero by set_mtfs())
- * times the multiplier, with an adjustment if we're actually using
- * less than the whole motif for some reason.
- * (b) Time may need to be quantised.
- * (c) Time of note is this tset-note + offset.
- */
- double getnotetime(noteptr phrasenote,double thistime,double multiplier,double timeadjust,dataptr dz)
- {
- int qunits;
- double timestep = ((double)phrasenote->ntime - timeadjust) * (double)multiplier; /* a */
- double thisgrid;
- if(dz->param[TEX_PHGRID]>0.0) {
- /* NEW 2000 */
- thisgrid = dz->param[TEX_PHGRID] * MS_TO_SECS;
- qunits = round(timestep/thisgrid); /* b */
- timestep = (double)(qunits*thisgrid);
- }
- return(thistime + timestep); /* c */
- }
- /************************ GETMTFDUR **********************************/
- int getmtfdur(noteptr tsetnote,noteptr phrasenote,double *dur,double multiplier,dataptr dz)
- {
- if(dz->vflag[DONT_KEEP_MTFDUR])
- *dur = tsetnote->dur;
- else
- *dur = phrasenote->dur * multiplier;
- if(flteq(*dur,0.0)) {
- sprintf(errstr,"TEXTURE: Problem 3 in getmtfdur(): Zero duration\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /***************************** ORN_OR_MTF_AMP_SETUP ************************************/
- int orn_or_mtf_amp_setup
- (int ampdirected,double *phrange,int phrno,double thisamp,int gpsize,double *rangemult,double *ampstep,
- unsigned char *amptype,unsigned char amptypestor,unsigned char amptypecnt,dataptr dz)
- {
- int exit_status;
- double kk;
- if(phrange[phrno]>=thisamp) {
- kk = (double)phrange[phrno]*((double)(gpsize+1)/(double)gpsize);
- *rangemult = (double)thisamp / kk;
- *ampstep = 0.0;
- } else {
- if(ampdirected) {
- if((exit_status = getmtfdirampstep(thisamp,phrange[phrno],amptypecnt,ampstep,gpsize,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = getmtfampstep(thisamp,phrange[phrno],ampstep,amptype,amptypestor,amptypecnt,gpsize,dz))<0)
- return(exit_status);
- }
- *rangemult = 1.0;
- }
- return(FINISHED);
- }
- /**************************** DO_MTF_PARAMS *******************************/
- int do_mtf_params
- (noteptr thisnote,double thisamp,noteptr phrasenote,noteptr tsetnote,
- double ampdif,double notetime,double multiplier,dataptr dz)
- {
- int exit_status;
- double duration;
- thisnote->amp = (float)(thisamp - ampdif);
- if((exit_status = getmtfdur(tsetnote,phrasenote,&duration,multiplier,dz))<0)
- return(exit_status);
- thisnote->dur = (float)duration;
- if((exit_status = do_grp_ins(tsetnote->instr,&(thisnote->instr),dz))<0)
- return(exit_status);
- thisnote->motioncentre = tsetnote->motioncentre;
- thisnote->ntime = (float)notetime;
- return(FINISHED);
- }
- /***************************** SETUP_MOTIF_OR_ORNAMENT ************************************/
- int setup_motif_or_ornament
- (double thistime,double *multiplier,int *phrno,noteptr *phrasenote,motifptr *phrase,dataptr dz)
- {
- int exit_status;
- if((exit_status = getvalue(TEX_MULTHI,TEX_MULTLO,thistime,PM_MULT,multiplier,dz))<0)
- return(exit_status);
- if((exit_status = doperm((int)dz->tex->phrasecnt,PM_WHICH,phrno,dz))<0)
- return(exit_status);
- *phrasenote = phrase[*phrno]->firstnote;
- return(FINISHED);
- }
- /****************************** POSITION_AND_SIZE_DECORATION **********************************/
- int position_and_size_decoration
- (double *thistime,double tsettime,double gpdense,int *gpsize,dataptr dz)
- {
- int exit_status;
- if((exit_status = get_dec_or_orn_pos(dz))<0)
- return(exit_status);
- if(dz->vflag[IS_PRE]) {
- if((*thistime -= gpdense * (double)((*gpsize) + 1))< -gpdense) {
- *thistime = tsettime;
- if((exit_status = subzero(thistime,gpdense,gpsize))<0)
- return(exit_status);
- }
- }
- return(FINISHED);
- }
- /****************************** SET_DECOR_AMP **********************************/
- int set_decor_amp
- (int ampdirected,double *thisamp,double *ampstep,int gpsize,
- unsigned char *amptype,unsigned char amptypecnt,unsigned char amptypestor,dataptr dz)
- {
- int exit_status;
- if(ampdirected) {
- if((exit_status = getdirampstep(*thisamp,amptypecnt,ampstep,gpsize,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = getampstep(ampstep,*thisamp,amptype,gpsize,amptypecnt,amptypestor,dz))<0)
- return(exit_status);
- }
- if(*ampstep>0.0)
- *thisamp -= (double)(gpsize+1) * (*ampstep);
- return(FINISHED);
- }
- /****************************** SET_GROUP_AMP **********************************/
- int set_group_amp
- (noteptr tsetnote,double *thisamp,unsigned char *amptype, double *ampstep,int gpsize,
- unsigned char amptypecnt,unsigned char amptypestor,dataptr dz)
- {
- int exit_status;
- if((exit_status = getampstep(ampstep,*thisamp,amptype,gpsize,amptypecnt,amptypestor,dz))<0)
- return(exit_status);
- if(*amptype==CRESC) {
- *thisamp -= (double)(gpsize) * (*ampstep);
- tsetnote->amp = (float)(*thisamp);
- }
- return(FINISHED);
- }
- /* LOCAL TO THESE GLOBALS */
- /****************************** ORN_SUBZERO *******************************
- *
- * Readjust the groupsize and the pointer to first note of phrase, where
- * otherwise phrase would start before zero.
- *
- * (1) Note the endtime of the phrase.
- * (2) For each note in the phrase.
- * (3) Find the duration of the phrase FROM THIS NOTE, by subtracting time of
- * current note from end (total) time, and adjusting by multiplier.
- * (4) If the duration of phrase from here, would put it's start after
- * zero-time, break from loop.
- * (5) Count number of notes rejected, and go to next phrase note.
- * (6) If we're at end of phrase, none of it's notes fall after zero time,
- * so return a gpsize of 0.
- * (7) Otherwise reset the event time (mifitime) to start of the group or
- * part-group which 'thisnote' points to.
- * (8) Resert the phrase pointer to point at this note of the phrase.
- * (9) When note times are finally calculated, timeadjust will reset all
- * the note times WITHIN the ornament to run from the note from
- * which we're starting, rather than the true start, by subtracting
- * 'timeadjust'.
- * (10) Return a size for the group reduced by the number of rejected notes.
- */
- void orn_subzero
- (double *thistime,noteptr phrlastnote,noteptr *phrasenote,double *timeadjust,double multiplier,int *gpsize)
- {
- double endtime = phrlastnote->ntime; /* 1 */
- double phrdur = 0.0;
- int cnt = 0;
- noteptr thisnote = *phrasenote;
- while(thisnote!=(noteptr)0) { /* 2 */
- phrdur = (endtime - thisnote->ntime) * multiplier; /* 3 */
- if(*thistime - phrdur >= 0.0) /* 4 */
- break;
- cnt++; /* 5 */
- thisnote = thisnote->next;
- }
- if(thisnote==(noteptr)0) {
- *gpsize = 0; /* 6 */
- return;
- } else {
- *thistime -= phrdur; /* 7 */
- *phrasenote = thisnote; /* 8 */
- *timeadjust = thisnote->ntime; /* 9 */
- }
- *gpsize -= cnt;
- return; /* 10 */
- }
- /*************************** GETMTFAMPSTEP ******************************
- *
- * Select flat, cresc or decresc, from available types, for motifs.
- *
- * (0) If the amplitude is bigger than the size of amprise and the
- * range of the phrase, taken together, amprise is OK as it is.
- * (00) Otherwise, amprise (set as ampstep at this point) is the amount
- * of the total amplitude left when the amplitude range of the phrase
- * has been subtracted. This ensures that no note of the phrase
- * can possibly end up below zero.
- * (1) IF the cresc will be from zero, clrzamp is 1, and this makes
- * the amplitude steps a little smaller, so that 1 of the notes
- * in sequence cannot be at amplitude zero.
- * OTHERWISE, clrzamp = 0, and ampstep is as normal.
- */
- int getmtfampstep(double amp,double framp,double *ampstep,unsigned char *amptype,
- unsigned char amptypestor,unsigned char amptypecnt,int gpsize,dataptr dz)
- {
- int exit_status;
- int clrzamp = 0;
- int k;
- if((exit_status = doperm((int)amptypecnt,PM_GPCNTR,&k,dz))<0)
- return(exit_status);
- if((exit_status=gettritype(k,amptypestor,amptype))<0)
- return(exit_status);
- if(*amptype==FLAT) { /**** FLAT *****/
- *ampstep =0.0;
- } else {
- if(amp>(dz->param[TEX_AMPRISE] + framp)) /* 0 */
- *ampstep = dz->param[TEX_AMPRISE];
- else {
- *ampstep = amp - framp; /* 00 */
- clrzamp = 1;
- }
- *ampstep /= (double)(gpsize+clrzamp); /* 1 */
- if(*amptype==DECRESC) /** DECRESCENDO **/
- *ampstep = -(*ampstep);
- }
- return(FINISHED);
- }
- /************************************************************************
- *
- * Calculating spatial orientation of motifs,groups,ornaments,decorations.
- */
- /**************************** SETSPACE *******************************/
- int setspace(noteptr tsetnote,noteptr thisnote,int gpsize,dataptr dz)
- {
- int exit_status;
- if(dz->iparam[TEX_GPSPACE]!=IS_STILL) {
- if((exit_status = space_gpnote(thisnote,gpsize,dz))<0)
- return(exit_status);
- } else
- thisnote->spacepos = tsetnote->spacepos;
- return(FINISHED);
- }
- /***************************** SPACE_GPNOTE *******************************
- *
- * (1) OUTSIDE THE GROUP- OR PHRASE-MAKING LOOP
- * (a) Need to know gpsize, dectype(is_post?), gpsprange
- * (which MUST be +ve!).
- * (b) Need to run 'init_group_spatialisation()' to establish spinit, & hence
- * range modifications etc.
- *
- * Then this will work INSIDE the loop.
- *
- * (1) NB !!!!! is_pre is defaulted to ZERO. This means that groups
- * or motifs which CANNOT BE pre- or post- are defaulted to
- * post (which means the groups start on the tset notes, rather
- * leading up to them).
- */
- int space_gpnote(noteptr thisnote,int gpsize,dataptr dz)
- {
- int exit_status;
- if(dz->iparam[TEX_GPSPACE]==IS_SCATTER) {
- if((exit_status = sp_scatter(thisnote,dz))<0)
- return(exit_status);
- } else {
- if(dz->vflag[IS_PRE]) { /* 1 */
- if((exit_status = pre_place(thisnote,gpsize,dz))<0)
- return(exit_status);
- } else {
- if((exit_status = post_place(thisnote,gpsize,dz))<0)
- return(exit_status);
- }
- }
- dz->iparam[SPINIT] = 0; /* disable initialisation after first call to group */
- return(FINISHED);
- }
- /**************************** SP_SCATTER *************************
- *
- * scatter group note around position of main event.
- */
- int sp_scatter(noteptr mnote,dataptr dz)
- {
- int exit_status;
- double sptop = 1.0, spbot= 0.0, hfthissprange,val;
- if(dz->param[THISSPRANGE]<=0.0) {
- mnote->spacepos = (float)dz->param[TPOSITION];
- return(FINISHED);
- }
- if(dz->iparam[SPINIT]) {
- hfthissprange = dz->param[THISSPRANGE]/(double)2.0;
- spbot = max((dz->param[TPOSITION] - hfthissprange),0.0);
- sptop = min((dz->param[TPOSITION] + hfthissprange),1.0);
- dz->param[THISSPRANGE] = sptop - spbot;
- }
- if((exit_status = pscatx(dz->param[THISSPRANGE],spbot,PM_GPSPAC,&val,dz))<0)
- return(exit_status);
- mnote->spacepos = (float)val;
- return(FINISHED);
- }
- /************** MACROS FOR RANGE REORIENTATIONS AND TRUNCATIONS **************
- *
- * r = group spatial range p = position of event
- * c = centre of motion d = direction of motion
- *
- * (1) If position to left of centre, reverse range.
- * (2) If position to right of centre, reverse range.
- * (3) If no motion, zero the range.
- * (4) If motion is right to left reverse range.
- * (5) If motion is left to right reverse range.
- * (6) avoid centre crossing
- * (7) avoid right-edge crossing
- * (8) avoid left-edge crossing
- * (9) avoid edge crossing
- */
- #define TURNOUTWARD(r,p,c) if((p)-(c)<0.0) (r) = -(r); /* 1 */
- #define TURNINWARD(r,p,c) if((p)-(c)>0.0) (r) = -(r); /* 2 */
- #define CHECKSTIL(r,d) if((d)==0) (r) = 0.0; /* 3 */
- #define FOLLOW(r,d) CHECKSTIL(r,d) else { if((d)<0) (r) = -(r); } /* 4 */
- #define CONTRARY(r,d) CHECKSTIL(r,d) else { if((d)>0) (r) = -(r); } /* 5 */
- #define SET_PRE_INRANGE(r,p,c) if(p<c) r = min(p,r); else r = max(p-1.0,r);
- #define FREECENTRE(r,p,c) if((r)>fabs((p)-(c))) (r)=fabs((p)-(c)); /* 6 */
- #define FREEREDGE(r,p) if((p)+(r)>1.0) (r) = 1.0 - (p); /* 7 */
- #define FREELEDGE(r,p) if((p)+(r)<0.0) (r) = -(p); /* 8 */
- #define FREEEDGES(r,p) if((r)>=0.0) { FREEREDGE((r),(p)) } else { FREELEDGE((r),(p)) }
- /* 9 */
- #define FREEREDGE_PRE(r,p) if((p)-(r)>1.0) (r) = (p) - 1.0; /* 7 */
- #define FREELEDGE_PRE(r,p) if((p)-(r)<0.0) (r) = (p); /* 8 */
- #define FREEEDGES_PRE(r,p) if((r)>=0.0) { FREELEDGE_PRE((r),(p)) } else { FREEREDGE_PRE((r),(p)) }
- /* 9 */
- /************************* PRE_PLACE *****************************
- *
- * place-in-space ornaments or decorations BEFORE notes, or motifs or groups
- * at texture points.
- *
- * is_pre = 1.
- */
- int pre_place(noteptr thisnote,int gpsize,dataptr dz)
- {
- if(dz->iparam[SPINIT])
- dz->iparam[SPCNT] = 0;
- switch(dz->iparam[TEX_GPSPACE]) {
- case(IS_STILL):
- dz->param[THISSPRANGE] = 0.0;
- break;
- case(IS_INWARD):
- if(dz->iparam[SPINIT]) {
- TURNINWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- SET_PRE_INRANGE(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- }
- break;
- case(IS_OUTWARD):
- if(dz->iparam[SPINIT]) {
- FREECENTRE(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- TURNOUTWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- }
- break;
- case(IS_FOLLOWING):
- if(dz->iparam[SPINIT]) {
- FOLLOW(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
- FREEEDGES_PRE(dz->param[THISSPRANGE],dz->param[TPOSITION])
- }
- break;
- case(IS_CONTRARY):
- if(dz->iparam[SPINIT]) {
- CONTRARY(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
- FREEEDGES_PRE(dz->param[THISSPRANGE],dz->param[TPOSITION])
- }
- break;
- default:
- sprintf(errstr,"TEXTURE: Invalid space-type %d in pre_place()\n",dz->iparam[TEX_GPSPACE]);
- return(PROGRAM_ERROR);
- }
- thisnote->spacepos = (float)(dz->param[TPOSITION] - dz->param[THISSPRANGE]
- + ((dz->param[THISSPRANGE]/(double)gpsize)*(double)(dz->iparam[SPCNT])));
- dz->iparam[SPCNT]++;
- return(FINISHED);
- }
-
- /************************* POST_PLACE *****************************
- *
- * place-in-space ornaments or decorations AFTER notes, or motifs or groups
- * at texture points.
- *
- * is_pre = 0, (or no ornament).
- */
- int post_place(noteptr thisnote,int gpsize,dataptr dz)
- {
- if(dz->iparam[SPINIT])
- dz->iparam[SPCNT] = 1;
- switch(dz->iparam[TEX_GPSPACE]) {
- case(IS_STILL):
- dz->param[THISSPRANGE] = 0.0;
- break;
- case(IS_INWARD):
- if(dz->iparam[SPINIT]) {
- FREECENTRE(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- TURNINWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- }
- break;
- case(IS_OUTWARD):
- if(dz->iparam[SPINIT]) {
- TURNOUTWARD(dz->param[THISSPRANGE],dz->param[TPOSITION],dz->param[CPOS])
- FREEEDGES(dz->param[THISSPRANGE],dz->param[TPOSITION])
- }
- break;
- case(IS_FOLLOWING):
- if(dz->iparam[SPINIT]) {
- FOLLOW(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
- FREEEDGES(dz->param[THISSPRANGE],dz->param[TPOSITION])
- }
- break;
- case(IS_CONTRARY):
- if(dz->iparam[SPINIT]) {
- CONTRARY(dz->param[THISSPRANGE],dz->iparam[DIRECTION])
- FREEEDGES(dz->param[THISSPRANGE],dz->param[TPOSITION])
- }
- break;
- default:
- sprintf(errstr,"TEXTURE: Invalid space-type %d in post_place()\n",dz->iparam[TEX_GPSPACE]);
- return(PROGRAM_ERROR);
- }
- thisnote->spacepos = (float)(dz->param[TPOSITION] +
- ((dz->param[THISSPRANGE]/(double)gpsize)*(double)(dz->iparam[SPCNT])));
- dz->iparam[SPCNT]++;
- return(FINISHED);
- }
- /************************** GPSP_INIT ***********************************
- *
- * Initialise the space-param for each group, before calling the spatialise
- * routines. 'spinit' causes initialisation of range etc elsewhere (in
- * pre_place() or post_place() ).
- */
- int init_group_spatialisation(noteptr tsetnote,int shaddoindex,noteptr *shadow,int shadowsize,dataptr dz)
- {
- int exit_status;
- dz->iparam[SPINIT] = 1;
- dz->param[TPOSITION] = tsetnote->spacepos;
- dz->param[CPOS] = tsetnote->motioncentre;
- if(dz->brksize[TEX_GRPSPRANGE]) { /* TABLE VALUES MUST BE 0 - 1 */
- if((exit_status = read_value_from_brktable((double)tsetnote->ntime,TEX_GRPSPRANGE,dz))<0)
- return(exit_status);
- }
- if(IS_DIRECTED(dz->iparam[TEX_GPSPACE]))
- dz->iparam[DIRECTION] = read_direction(shaddoindex,shadow,shadowsize);
- dz->param[THISSPRANGE] = dz->param[TEX_GRPSPRANGE];
- return(FINISHED);
- }
- /**************************** READ_DIRECTION ****************************
- *
- * Read direction of motion from spatial position stored in note.
- *
- * NB: as the tset is in the process of being modified, we cannot
- * refer directly to the tset linked list. We can only access the original
- * tset through it's 'shadow'.
- *
- * (0) Save the time of the current note as 'now'.
- * (1) Save position of current note as 'here'.
- * (2) Whilever we're not at the end of the tset (shadow).
- * (a) Note time of next note, store as 'then'.
- * (b) If 'then' is later than 'now'.
- * Note position of new note as 'there'.
- * Set as OK and break out of loop.
- * (3) If it's not OK (i.e. we were at, or came to the end of the tset
- * (shadow))....
- * (a) Go back to where we started.
- * (b) Call this position 'there'.
- * (4) While ever we're not at beginning of tset...
- * (a) Note time of previous note, store as 'then'.
- * (b) If 'then' is 'earlier' than 'now'...
- * Note position of new note as 'here'.
- * Set as OK and break out of loop.
- * (5) If still not OK, then there is no more than 1 (non-simultaneous)
- * event in the tset, so therefore no motion, so return 0.
- * (6) If there>here, left-to-right motion, return 1.
- * (7) If here>there, right-to-left motion, return -1.
- * (8) Otherwise, no motion, return 0.
- */
- int read_direction(int shi,noteptr *shadow,int shadowsize)
- {
- unsigned char OK;
- float here, there = 0.0;
- double now, then;
- int startshi = shi;
- now = (shadow[shi])->ntime; /* 0 */
- here = (shadow[shi])->motioncentre; /* 1 */
- OK = 0;
- while(++shi<shadowsize) { /* 2 */
- then = (shadow[shi])->ntime; /* a */
- if(then>(now+FLTERR)) { /* b */
- there = (shadow[shi])->motioncentre;
- OK = 1;
- break;
- }
- }
- if(!OK) { /* 3 */
- shi = startshi; /* a */
- there = here; /* b */
- while(--shi>=0) { /* 4 */
- then = (shadow[shi])->ntime; /* a */
- if(then<(now-FLTERR)) { /* b */
- here = (shadow[shi])->motioncentre;
- OK = 1;
- break;
- }
- }
- }
- if(!OK)
- return(0); /* 5 */
- if(there>here) /* 6 */
- return(1);
- if(there<here) /* 7 */
- return(-1);
- return(0); /* 8 */
- }
- /*************************** GETAMPSTEP ******************************
- *
- * Select flat, cresc or decresc, from available types.
- *
- * (1) IF the cresc will be from zero, clrzamp is 1, and this makes
- * the amplitude steps a little smaller, so that 1st note in sequence
- * will not be at amplitude zero.
- * OTHERWISE, clrzamp = 0, and ampstep is as normal.
- */
- int getampstep
- (double *ampstep,double amp,unsigned char *amptype,int gpsize,unsigned char amptypecnt,
- unsigned char amptypestor,dataptr dz)
- {
- int exit_status;
- int clrzamp = 0, k;
- /*int texflag = dz->tex->txflag;*/
- if((exit_status = doperm((int)amptypecnt,PM_GPCNTR,&k,dz))<0)
- return(exit_status);
- if((exit_status = gettritype(k,amptypestor,amptype))<0)
- return(exit_status);
- if(*amptype==FLAT) /**** FLAT *****/
- *ampstep =0.0;
- else {
- *ampstep = dz->param[TEX_AMPRISE]; /* param with <|> option */
-
- if(*ampstep>=amp) {
- clrzamp = 1;
- *ampstep = amp;
- }
- *ampstep /= (double)(gpsize + clrzamp); /* 1 */
- if(*amptype==DECRESC) /** DECRESCENDO **/
- *ampstep = -(*ampstep);
- }
- return(FINISHED);
- }
- /*************************** GETDIRAMPSTEP ******************************
- *
- * (1) If there are two amplitude types, in THIS CASE, these can only
- * be DIRECTED or FLAT. So...
- * (2) Choose flat or directed via perm.
- * (3) and if it's flat, return an ampstep of zero.
- * Otherwise, we proceed as in the normal case of a directed amp.
- * (4) Set initial ampstep to amprise.
- * (5) IF the cresc will be from zero, or decresc to zero, clrzamp is 1,
- * and this makes the amplitude steps a little smaller, so that 1st note
- * of cresc (or last note of decresc) will not be at amplitude zero.
- * OTHERWISE, clrzamp = 0, and ampstep is as normal.
- * (6) Divide ampstep by number of members in group.
- * (7) If it's a post-ornament, ampstep is negative.
- */
- int getdirampstep
- (double amp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz)
- {
- int exit_status;
- int k, clrzamp = 0;
- if(amptypecnt==2) { /* 1 */
- if((exit_status= doperm((int)2,PM_GPCNTR,&k,dz))<0) /* 2 */
- return(exit_status);
- if(k==0) {
- *ampstep = 0.0;
- return(FINISHED); /* 3 */
- }
- }
- *ampstep = dz->param[TEX_AMPRISE]; /* param with <|> option */ /* 4 */
- if(*ampstep>=amp) { /* 5 */
- clrzamp = 1;
- *ampstep = amp;
- }
- *ampstep /= (double)(gpsize + clrzamp); /* 6 */
- if(!dz->vflag[IS_PRE]) /* 7 */
- *ampstep = -(*ampstep);
- return(FINISHED);
- }
- /*************************** GETMTFDIRAMPSTEP *******************************
- *
- * Intelligent guesswork!! Nov 4: 1997
- */
- int getmtfdirampstep(double amp,double framp,unsigned char amptypecnt,double *ampstep,int gpsize,dataptr dz)
- {
- int exit_status;
- int k, clrzamp = 0;
- if(amptypecnt==2) { /* 1 */
- if((exit_status= doperm((int)2,PM_GPCNTR,&k,dz))<0) /* 2 */
- return(exit_status);
- if(k==0) {
- *ampstep = 0.0;
- return(FINISHED); /* 3 */
- }
- }
- if(amp>(dz->param[TEX_AMPRISE] + framp))
- *ampstep = dz->param[TEX_AMPRISE];
- else {
- *ampstep = amp - framp;
- clrzamp = 1;
- }
- *ampstep /= (double)(gpsize + clrzamp); /* 6 */
- if(!dz->vflag[IS_PRE]) /* 7 */
- *ampstep = -(*ampstep);
- return(FINISHED);
- }
- /************************* GET_DEC_OR_ORN_POS ***************************
- *
- * Decuptype flags are selected and shifted down into the range 0-3
- * If its 01 (1), it's a post-ornament, so set 'is_pre' = FALSE.
- * If its 10 (2), it's a pre_ornament, so set 'is_pre' = TRUE
- * If its 00 (0), it's not set, so we select 'is_pre' at random using doperm on 2 (output 0S or 1).
- *
- * NB: If we are using a group or motif, rather than a decoration
- * or ornament, is_pre is BY DEFAULT set to 0.
- */
- int get_dec_or_orn_pos(dataptr dz)
- {
- int exit_status;
- int k;
- unsigned int dectype = dz->tex->txflag & GET_DECORNPOS;
- switch(dectype) {
- case(1): dz->vflag[IS_PRE] = TRUE; break;
- case(2): dz->vflag[IS_PRE] = FALSE; break;
- default:
- if((exit_status = doperm((int)2,PM_ORNPOS,&k,dz))<0)
- return(exit_status);
- dz->vflag[IS_PRE] = (char)k;
- break;
- }
- if(dz->vflag[IS_PRE] > 1) {
- sprintf(errstr,"Error from perm in get_dec_or_orn_pos()\n");
- return(PROGRAM_ERROR);
- }
- return(FINISHED);
- }
- /**************************** SUBZERO ***********************************
- *
- * If start of a decoration falls before time zero, adjust its size
- * and hence starttime(-minus-gpdense) appropriately.
- */
- int subzero(double *thistime,double gpdense,int *gpsize)
- {
- int n = -1;
- while(*thistime>=0.0) {
- *thistime -= gpdense;
- n++;
- }
- if(n<0) {
- sprintf(errstr,"TEXTURE: Problem in subzero()\n");
- return(PROGRAM_ERROR);
- }
- *gpsize = n;
- return(FINISHED);
- }
- /*************************** GETHIPITCH *********************************#
- *
- * Find highest pitch at current time.
- */
- noteptr gethipitch(noteptr tsetnote,int *shaddoindex)
- {
- noteptr hinote, thisnote;
- double hipitch;
- int zz = *shaddoindex;
- hinote = thisnote = tsetnote;
- hipitch = (double)hinote->pitch;
- while(thisnote->next!=(noteptr)0) {
- if(thisnote->next->ntime > thisnote->ntime + FLTERR)
- return(hinote);
- thisnote = thisnote->next;
- zz++;
- if((double)thisnote->pitch > hipitch) {
- hipitch = (double)thisnote->pitch;
- hinote = thisnote;
- (*shaddoindex) = zz;
- }
- }
- return(hinote);
- }
- /****************************** DO_GRP_INS **********************************
- *
- * Choose instr-no within group/decoration/motif or ornament.
- * Values of instr-no range are preset when instr is chosen for the
- * tset, in do_ev_ins().
- */
- int do_grp_ins(unsigned char thisinstr,unsigned char *val,dataptr dz)
- {
- int exit_status;
- int irange, ival;
- if(dz->vflag[INS_TO_SCATTER]) {
- if((irange = (int)(dz->iparam[TEXTURE_INSHI] - dz->iparam[TEXTURE_INSLO])) < 0) {
- iswap((int *)&(dz->iparam[TEXTURE_INSHI]),(int *)&(dz->iparam[TEXTURE_INSLO]));
- irange = -irange;
- }
- if(irange==0)
- *val = (unsigned char)dz->iparam[TEXTURE_INSLO];
- else {
- if((exit_status = doperm(irange+1,PM_INSNO,&ival,dz))<0) /* range INCLUSIVE for ints */
- return(exit_status);
- *val = (unsigned char)(ival + dz->iparam[TEXTURE_INSLO]);
- }
- } else
- *val = thisinstr;
- return(FINISHED);
- }
- /***************************** PSCATX ************************************
- *
- * Select a random value within 'range', by permuting one of BANDCNT equal
- * ranges, and selecting a random value within the chosen range.
- */
- int pscatx(double range,double bottom,int pindex,double *val,dataptr dz)
- {
- int k, exit_status;
- double bandwidth, bandbottom, x;
- if((exit_status = doperm((int)BANDCNT,pindex,&k,dz))<0)
- return(exit_status);
- bandwidth = range/(double)BANDCNT;
- bandbottom = (double)k * bandwidth;
- x = (drand48() * bandwidth);
- x += bandbottom;
- *val = x + bottom;
- return(FINISHED);
- }
- /*************************** DEL_NOTE ************************************/
- void del_note(noteptr thisnote,motifptr thismotif)
- {
- if(thisnote->next!=(noteptr)0)
- thisnote->next->last = thisnote->last; /* 1 */
- if(thisnote->last!=(noteptr)0)
- thisnote->last->next = thisnote->next; /* 2 */
- else
- thismotif->firstnote = thisnote->next; /* 3 */
- free(thisnote); /* 4 */
- }
-
- /************************** TIMESORT ****************************
- *
- * Timesorts notes in a list
- *
- * (1) Move the item with earliest time to start of list, and set this
- * (minimum) time as maximum time also.
- * For each item in the list....
- * (2) If this item is earlier than current latest item (maxtime)..
- * (3) Find where it should be in the list.
- * (4) move it to that location.
- * (5) Otherwise, set this item's time as latest time(maxtime).
- * (6) Reset motifhead to start of notelist!!
- */
- int arrange_notes_in_timeorder(motifptr mtf)
- {
- noteptr base, here, there, mark;
- double thistime, maxtime;
- if((base = mtf->firstnote)==(noteptr)0)
- return(FINISHED);
- maxtime = setup_first_notelist_time(&base); /* 1 */
- here = base;
- while(here!=(noteptr)0) {
- if((thistime = here->ntime) < maxtime) { /* 2 */
- if((mark = here->last)==(noteptr)0) {
- sprintf(errstr,"Problem (1) in arrange_notes_in_timeorder()\n");
- return(PROGRAM_ERROR);
- }
- if((there = reverse_search_for_time(here,thistime))==(noteptr)0) {
- sprintf(errstr,"Timing problem in arrange_notes_in_timeorder()\n");
- return(PROGRAM_ERROR);
- } /* 3 */
- move_notelist_item(here,there); /* 4 */
- here = mark;
- } else
- maxtime = here->ntime; /* 5 */
- here = here->next;
- }
- return reset_mtfhead(mtf); /* 6 */
- }
- /************************* RESET_MTFHEAD ***************************
- *
- * Reset pointer to start of notelist.
- */
-
- int reset_mtfhead(motifptr mtf)
- {
- noteptr here = mtf->firstnote;
- if(mtf->firstnote==NULL) {
- sprintf(errstr,"Problem in reset_mrfhead()\n");
- return(PROGRAM_ERROR);
- }
- while(here->last!=(noteptr)0)
- here = here->last;
- mtf->firstnote = here;
- return(FINISHED);
- }
- /************************** SETUP_FIRST_NOTELIST_TIME ***************************
- *
- * Put the earliest timed item in a list of notes into start of list.
- */
- double setup_first_notelist_time(noteptr *base)
- {
- noteptr firstnote, here;
- double mintime, thistime;
- firstnote = here = *base;
- mintime = (*base)->ntime;
- while(here!=(noteptr)0) {
- if((thistime = here->ntime)<mintime) {
- firstnote = here;
- mintime = thistime;
- }
- here = here->next;
- }
- if(firstnote!=(*base)) {
- move_notelist_item(firstnote,(*base));
- *base = firstnote;
- }
- return(mintime);
- }
- /************************* MOVE_NOTELIST_ITEM ***************************
- *
- * Move an item in a notelist from location a to BEFORE location b.
- */
- void move_notelist_item(noteptr a,noteptr b)
- {
- if(a->last!=(noteptr)0)
- a->last->next = a->next;
- if(a->next!=(noteptr)0)
- a->next->last = a->last;
- a->next = b;
- a->last = b->last;
- if(b->last!=(noteptr)0)
- b->last->next = a;
- b->last = a;
- }
- /************************** REVERSE_SEARCH_FOR_TIME *****************************
- *
- * Reverse search note-list using a time as index, and return address
- * of note whose time is AFTER the input time.
- * WILL RETURN (noteptr)0 IF REFTIME IS OFF END OF LIST.
- */
- noteptr reverse_search_for_time(noteptr start,double reftime)
- {
- noteptr here = start;
- while(here->ntime >= reftime) {
- if(here->last == (noteptr)0)
- return(here);
- here = here->last;
- }
- return(here->next);
- }
- /************************** ISWAP *****************************/
- void iswap(int *a,int *b)
- {
- int temp;
- temp = *a;
- *a = *b;
- *b = temp;
- }
- /****************************** SET_GROUP_PARAMS **********************************/
- int set_group_params
- (noteptr tsetnote,noteptr thisnote,double gpdense,double ampstep,double *thisamp,double *thistime,double thisdur,dataptr dz)
- {
- int exit_status;
- double thisgpdense, time_left;
- *thisamp += ampstep;
- thisnote->amp = (float)*thisamp;
- thisnote->dur = (float)thisdur;
- if(dz->vflag[FIXED_STEP])
- *thistime += gpdense;
- else {
- if((exit_status = get_density_val(*thistime,&thisgpdense,dz))<0)
- return(exit_status);
- if((dz->tex->txflag & IS_DECOR) && dz->vflag[IS_PRE]) {
- if((time_left = tsetnote->ntime - *thistime)<0.0) {
- sprintf(errstr,"Error in assumptions: set_group_params()\n");
- return(PROGRAM_ERROR);
- }
- time_left *= 0.66;
- thisgpdense = min(time_left,thisgpdense);
- }
- *thistime += thisgpdense;
- }
- return(FINISHED);
- }
- /***************************** GETTRITYPE *****************************
- *
- * Choose a type, from up to three available types in bit-flag.
- * e.g.
- * Choose an amplitude type (flat,cresc,decresc) from 3 available types.
- * Choose a decoration-orientation type (above,below,mid) from 3 types.
- *
- * (1) For each type in the bitflag.
- * (2) If this option is flagged, count it.
- * (3) IF this option is chosen, return its bit-number.
- * (4) Advance the bitflag mask.
- */
- int gettritype(int k,unsigned stor,unsigned char *val)
- {
- int v = 0, mask = 1, n;
- k++;
- for(n=0;n<3;n++) { /* 1 */
- if(mask & stor) /* 2 */
- v++;
- if(k==v) { /* 3 */
- *val = (unsigned char)n;
- return(FINISHED);
- }
- mask <<= 1; /* 4 */
- }
- sprintf(errstr,"TEXTURE: Problem in gettritype()\n");
- return(PROGRAM_ERROR);
- }
- /*************************** GET_DENSITY_VAL ******************************/
- int get_density_val(double thistime,double *gpdense,dataptr dz)
- {
- int exit_status;
- if((exit_status = getvalue(TEX_GPPACKHI,TEX_GPPACKLO,thistime,PM_GPDENS,gpdense,dz))<0)
- return(PROGRAM_ERROR);
- /* NEW MAR 2000 */
- *gpdense *= MS_TO_SECS;
- if(dz->param[TEX_PHGRID]>0.0)
- *gpdense = quantise(*gpdense,dz->param[TEX_PHGRID]);
- return FINISHED;
- }
- /**************************** SET_MOTIFS *******************************
- *
- * initialise all parameters of input motifs to be used for MOTIFS or
- * ORNAMENTS.
- *
- * (1)For each input motif (called a 'phrase').
- * phrnotecnt[n] = 0;
- * (2) Initialise count of number of notes to 0, maximum amplitude
- * of phrase to 0.0, and lowest pitch to MIDITOP.
- * (3) Go through each note of the motif.
- * (4) Add up the number of notes in it.
- * (5) Find it's lowest pitch.
- * (6) Find it's loudest note (and set as phraseamp).
- * (7) Establish dynamic range of phrase.
- * (8) Transpose the motif into it's lowest possible register.
- * (9) Ensure motif starts at zero time.
- * (10) Store addresses of last notes in phrases.
- */
- int set_motifs
- (int phrcount,motifptr *phrase,int *phrnotecnt,double *phraseamp,double *phrange,noteptr *phrlastnote)
- {
- int exit_status;
- int n;
- double minpitch, mintime, minamp;
- noteptr thisnote, lastnote = (noteptr)0;
- for(n=0;n<phrcount;n++) { /* 1 */
- if((exit_status = arrange_notes_in_timeorder(phrase[n]))<0)
- return(exit_status);
- phrnotecnt[n] = 0;
- phraseamp[n] = 0.0; /* 2 */
- minamp = DBL_MAX;
- minpitch = MIDITOP;
- mintime = DBL_MAX;
- thisnote = phrase[n]->firstnote; /* 3 */
- while(thisnote!=(noteptr)0) {
- phrnotecnt[n]++; /* 4 */
- if(thisnote->pitch<minpitch)
- minpitch = thisnote->pitch; /* 5 */
- if(thisnote->ntime<mintime)
- mintime = thisnote->ntime; /* 5 */
- if((double)thisnote->amp>phraseamp[n])
- phraseamp[n] = (double)thisnote->amp;/* 6 */
- if(thisnote->amp<minamp)
- minamp = thisnote->amp; /* 6 */
- thisnote = thisnote->next;
- }
- if(minamp == DBL_MAX || mintime == DBL_MAX) {
- sprintf(errstr,"Error parsing motif: set_motifs()\n");
- return(PROGRAM_ERROR);
- }
- thisnote = phrase[n]->firstnote;
- phrange[n] = phraseamp[n] - minamp; /* 7 */
- while(thisnote!=(noteptr)0) {
- thisnote->pitch = (float)(thisnote->pitch - (minpitch + MIDIBOT)); /* 8 */
- thisnote->ntime = (float)(thisnote->ntime - mintime); /* 9 */
- lastnote = thisnote; /* 10 */
- thisnote = thisnote->next;
- }
- if((phrlastnote[n] = lastnote) == (noteptr)0) {
- sprintf(errstr,"Zero length phrase encountered: set_motifs()\n");
- return(PROGRAM_ERROR);
- }
- }
- return(FINISHED);
- }
- void cyclicperm(dataptr dz)
- {
- int n, t;
- do {
- for(n=0;n<dz->infilecnt;n++) {
- t = (int)floor(drand48() * (n+1));
- if(t==n) {
- hprefix(n,dz->peakno,dz->infilecnt);
- } else {
- hinsert(n,t,dz->peakno,dz->infilecnt);
- }
- }
- } while(dz->peakno[0] == dz->lastpeakno[dz->infilecnt - 1]); // Avoid repetitions at perm boundaries.
- for(n=0;n<dz->infilecnt;n++)
- dz->lastpeakno[n] = dz->peakno[n];
- }
- void hinsert(int m,int t,int *perm,int permlen)
- {
- hshuflup(t+1,perm,permlen);
- perm[t+1] = m;
- }
- void hprefix(int m,int *perm,int permlen)
- {
- hshuflup(0,perm,permlen);
- perm[0] = m;
- }
- void hshuflup(int k,int *perm,int permlen)
- {
- int n, *i;
- int z = permlen - 1;
- i = perm+z;
- for(n = z;n > k;n--) {
- *i = *(i-1);
- i--;
- }
- }
- #ifndef round
- int round(double a)
- {
- return (int)floor(a + 0.5);
- }
- #endif
|