strands.c 142 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314
  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. // Attempted to integrate a "-b" flag that synthesizes the bands
  22. // One after another (rather trhan superimposed)
  23. // NEED TO TEST HIS WORKS (and test orig not broken)
  24. // This code saved on STICK
  25. // ORIG_CODE saved as strand_orig.c ***
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include <structures.h>
  29. #include <tkglobals.h>
  30. #include <pnames.h>
  31. #include <filetype.h>
  32. #include <processno.h>
  33. #include <modeno.h>
  34. #include <logic.h>
  35. #include <globcon.h>
  36. #include <cdpmain.h>
  37. #include <math.h>
  38. #include <mixxcon.h>
  39. #include <osbind.h>
  40. #include <science.h>
  41. #include <standalone.h>
  42. #include <ctype.h>
  43. #include <sfsys.h>
  44. #include <string.h>
  45. #include <srates.h>
  46. #ifdef unix
  47. #include <aaio.h>
  48. #endif
  49. #define STRAND_SRATE (44100)
  50. #define STRAND_MAXWARP (3) // Max timewarp, takes 0-1 line and, at max(min) cubes (or cube-roots) values,
  51. // to give concave or convex distortion of 0-1 value line.
  52. #define WAVYFRAC (0.4) // Boundary of band, during wavy-band-turbulence, can wander to max of 2/5 of bandwidth up or down.
  53. #define TURBPOW (0.5) // Random 0-1 LEVEL values, raised to this power, to weight them towards louder vals dominating
  54. #define TURBFLATTEN (2.0) // As turbulence kicks in (in range 0 -> 1), any waviness of band boundaries flattens out.
  55. // Amplitude of waves is related to value of (1 - turbulence), (range 1 -> 0)
  56. // The straight line of this function is made concave by this power factor
  57. // So amplitude dips more quickly towards zero at start of any turbulence.
  58. #define splicesize rampbrksize
  59. #define datasize temp_sampsize
  60. #define subbanded is_mapping
  61. #define derivs is_transpos
  62. #define rotmix is_transpos
  63. #define sintable is_rectified
  64. #define costable specenv_type
  65. #define sinptrs zeroset
  66. #define frqstores fzeroset
  67. #define tessitura is_flat
  68. #define scaler is_sharp
  69. #define rotlevel could_be_pitch
  70. #define levderivs could_be_transpos
  71. #define flowdata descriptor_samps
  72. #define flowcnt ringsize
  73. #define twist dz->brk[STRAND_TWIST]
  74. #define LAMINAR 0
  75. #define TOTWIST 1
  76. #define FROMTWIST 2
  77. #define TWISTED 3
  78. #define ROOT2 (1.4142136)
  79. #define SIGNAL_TO_LEFT (0)
  80. #define SIGNAL_TO_RIGHT (1)
  81. #ifdef unix
  82. #define round(x) lround((x))
  83. #endif
  84. char errstr[2400];
  85. int anal_infiles = 1;
  86. int sloom = 0;
  87. int sloombatch = 0;
  88. const char* cdp_version = "7.0.0";
  89. //CDP LIB REPLACEMENTS
  90. static int setup_strands_application(dataptr dz);
  91. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  92. static int setup_strands_param_ranges_and_defaults(dataptr dz);
  93. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
  94. static int open_the_outfile(char *sfnam,dataptr dz);
  95. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  96. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  97. static int establish_application(dataptr dz);
  98. static int initialise_vflags(dataptr dz);
  99. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  100. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  101. static int mark_parameter_types(dataptr dz,aplptr ap);
  102. static int assign_file_data_storage(int infilecnt,dataptr dz);
  103. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  104. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  105. static int get_the_mode_from_cmdline(char *str,dataptr dz);
  106. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  107. static int strands_param_preprocess(double *pitchrange,double *band_separation,double *tessitura,int *isturb,int threadvalscnt,dataptr dz);
  108. static int synthesis(dataptr dz);
  109. //static void incr_sinptr(int n,double time,double onehzincr,dataptr dz);
  110. //static double read_level(int n,double time,dataptr dz);
  111. static int create_strands_sndbufs(dataptr dz);
  112. static int spline(int streamno,int islevel,dataptr dz);
  113. static double splint(int streamno,double time,int islevel,dataptr dz);
  114. static int create_next_outfile(int no, char *sfnam, char *temp,dataptr dz);
  115. static void scatter_streamdata_in_last_cycle(double time,int bandno,int threadscnt,int threadbas, int outcnt,double lastcycendtime,dataptr dz);
  116. static double wavy(int bandno,double bandtop_mean,double tessitura,double amp,double *wavyfrq,double *tabpos,int *cycend,double scaling,dataptr dz);
  117. static int establish_flow_types(dataptr dz);
  118. static int get_flow_type(double time,double *transitstart,double *twistreffrq,double *transittime,dataptr dz) ;
  119. static double turblevel(double turbulence,double thislevel,dataptr dz);
  120. static int check_turbulence_values(int *isturb,dataptr dz);
  121. static void assign_turbulence_pitches(int streamcnt,double pitchbot,double pitchrange,int *perm,double *turbpset,double *turbpitch);
  122. static void pancalc(double position,double *leftgain,double *rightgain);
  123. static double sinread(int iscos,double *tabpos,double frq,int *cycend,double scaling,dataptr dz);
  124. static int strands(double pitchrange,double band_separation,double tessitura,int isturb,dataptr dz);
  125. static int output_strands(char *sfnam,dataptr dz);
  126. static int handle_the_special_data(int *cmdlinecnt,char ***cmdline,int *threadvalscnt,dataptr dz);
  127. /**************************************** MAIN *********************************************/
  128. int main(int argc,char *argv[])
  129. {
  130. int exit_status;
  131. dataptr dz = NULL;
  132. char **cmdline, sfnam[400];
  133. int cmdlinecnt, k, isturb = 0, threadvalscnt = 0;
  134. double pitchrange, band_separation, tessitura;
  135. aplptr ap;
  136. int is_launched = FALSE;
  137. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  138. fprintf(stdout,"%s\n",cdp_version);
  139. fflush(stdout);
  140. return 0;
  141. }
  142. /* CHECK FOR SOUNDLOOM */
  143. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  144. sloom = 0;
  145. sloombatch = 1;
  146. }
  147. if(sflinit("cdp")){
  148. sfperror("cdp: initialisation\n");
  149. return(FAILED);
  150. }
  151. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  152. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  153. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  154. return(FAILED);
  155. }
  156. if(!sloom) {
  157. if(argc == 1) {
  158. usage1();
  159. return(FAILED);
  160. } else if(argc == 2) {
  161. usage2(argv[1]);
  162. return(FAILED);
  163. }
  164. }
  165. if(!sloom) {
  166. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  167. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  168. return(FAILED);
  169. }
  170. cmdline = argv;
  171. cmdlinecnt = argc;
  172. if((get_the_process_no(argv[0],dz))<0)
  173. return(FAILED);
  174. cmdline++;
  175. cmdlinecnt--;
  176. dz->maxmode = 3;
  177. if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
  178. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  179. return(exit_status);
  180. }
  181. cmdline++;
  182. cmdlinecnt--;
  183. // setup_particular_application =
  184. if((exit_status = setup_strands_application(dz))<0) {
  185. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  186. return(FAILED);
  187. }
  188. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  189. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  190. return(FAILED);
  191. }
  192. } else {
  193. //parse_TK_data() =
  194. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  195. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  196. return(exit_status);
  197. }
  198. }
  199. ap = dz->application;
  200. dz->infile->channels = 2;
  201. dz->infile->srate = STRAND_SRATE;
  202. // parse_infile_and_hone_type() =
  203. // setup_param_ranges_and_defaults() =
  204. if((exit_status = setup_strands_param_ranges_and_defaults(dz))<0) {
  205. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  206. return(FAILED);
  207. }
  208. // open_first_infile() : redundant
  209. // handle_extra_infiles() : redundant
  210. // handle_outfile() =
  211. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
  212. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  213. return(FAILED);
  214. }
  215. // handle_formants() redundant
  216. // handle_formant_quiksearch() redundant
  217. strcpy(sfnam,dz->outfilename);
  218. if(sloom) {
  219. k = strlen(sfnam);
  220. k--;
  221. *(sfnam + k) = ENDOFSTR; // (shorten generic filename by 1 cyaracter, discarding "0"
  222. }
  223. if(dz->mode == 2) {
  224. if((exit_status = handle_the_special_data(&cmdlinecnt,&cmdline,&threadvalscnt,dz))<0) {
  225. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  226. return(FAILED);
  227. }
  228. }
  229. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  230. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  231. return(FAILED);
  232. }
  233. if(dz->iparam[STRAND_SEED] > 0) {
  234. srand((int)dz->iparam[STRAND_SEED]);
  235. }
  236. // check_param_validity_and_consistency() redundant
  237. is_launched = TRUE;
  238. if(dz->mode == 1) {
  239. if((exit_status = create_strands_sndbufs(dz))<0) { // CDP LIB
  240. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  241. return(FAILED);
  242. }
  243. }
  244. if((exit_status = strands_param_preprocess(&pitchrange,&band_separation,&tessitura,&isturb,threadvalscnt,dz))<0) {
  245. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  246. return(FAILED);
  247. }
  248. if(EVEN(dz->mode) && !sloom)
  249. strcat(dz->outfilename,"0.txt");
  250. if((exit_status = open_the_outfile(dz->outfilename,dz))<0) {
  251. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  252. return(FAILED);
  253. }
  254. // process_file =
  255. if((exit_status = strands(pitchrange,band_separation,tessitura,isturb,dz))<0) {
  256. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  257. return(FAILED);
  258. }
  259. if(dz->mode == 1) {
  260. if((exit_status = synthesis(dz))<0) {
  261. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  262. return(FAILED);
  263. }
  264. } else {
  265. if((exit_status = output_strands(sfnam,dz))<0) {
  266. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  267. return(FAILED);
  268. }
  269. }
  270. if((exit_status = complete_output(dz))<0) { // CDP LIB
  271. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  272. return(FAILED);
  273. }
  274. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  275. free(dz);
  276. return(SUCCEEDED);
  277. }
  278. /**********************************************
  279. REPLACED CDP LIB FUNCTIONS
  280. **********************************************/
  281. /****************************** SET_PARAM_DATA *********************************/
  282. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  283. {
  284. ap->special_data = (char)special_data;
  285. ap->param_cnt = (char)paramcnt;
  286. ap->max_param_cnt = (char)maxparamcnt;
  287. if(ap->max_param_cnt>0) {
  288. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  289. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  290. return(MEMORY_ERROR);
  291. }
  292. strcpy(ap->param_list,paramlist);
  293. }
  294. return(FINISHED);
  295. }
  296. /****************************** SET_VFLGS *********************************/
  297. int set_vflgs
  298. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  299. {
  300. ap->option_cnt = (char) optcnt; /*RWD added cast */
  301. if(optcnt) {
  302. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  303. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  304. return(MEMORY_ERROR);
  305. }
  306. strcpy(ap->option_list,optlist);
  307. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  308. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  309. return(MEMORY_ERROR);
  310. }
  311. strcpy(ap->option_flags,optflags);
  312. }
  313. ap->vflag_cnt = (char) vflagcnt;
  314. ap->variant_param_cnt = (char) vparamcnt;
  315. if(vflagcnt) {
  316. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  317. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  318. return(MEMORY_ERROR);
  319. }
  320. strcpy(ap->variant_list,varlist);
  321. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  322. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  323. return(MEMORY_ERROR);
  324. }
  325. strcpy(ap->variant_flags,varflags);
  326. }
  327. return(FINISHED);
  328. }
  329. /***************************** APPLICATION_INIT **************************/
  330. int application_init(dataptr dz)
  331. {
  332. int exit_status;
  333. int storage_cnt;
  334. int tipc, brkcnt;
  335. aplptr ap = dz->application;
  336. if(ap->vflag_cnt>0)
  337. initialise_vflags(dz);
  338. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  339. ap->total_input_param_cnt = (char)tipc;
  340. if(tipc>0) {
  341. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  342. return(exit_status);
  343. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  344. return(exit_status);
  345. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  346. return(exit_status);
  347. }
  348. brkcnt = tipc;
  349. //THERE ARE NO INPUTFILE brktables USED IN THIS PROCESS
  350. if(brkcnt>0) {
  351. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  352. return(exit_status);
  353. }
  354. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  355. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  356. return(exit_status);
  357. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  358. return(exit_status);
  359. }
  360. if((exit_status = mark_parameter_types(dz,ap))<0)
  361. return(exit_status);
  362. // establish_infile_constants() replaced by
  363. dz->infilecnt = 1;
  364. //establish_bufptrs_and_extra_buffers():
  365. return(FINISHED);
  366. }
  367. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  368. /* RWD mallo changed to calloc; helps debug verison run as release! */
  369. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  370. {
  371. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  372. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  373. return(MEMORY_ERROR);
  374. }
  375. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  376. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  377. return(MEMORY_ERROR);
  378. }
  379. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  380. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  381. return(MEMORY_ERROR);
  382. }
  383. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  384. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  385. return(MEMORY_ERROR);
  386. }
  387. return(FINISHED);
  388. }
  389. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  390. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  391. {
  392. int n;
  393. for(n=0;n<storage_cnt;n++) {
  394. dz->is_int[n] = (char)0;
  395. dz->no_brk[n] = (char)0;
  396. }
  397. return(FINISHED);
  398. }
  399. /***************************** MARK_PARAMETER_TYPES **************************/
  400. int mark_parameter_types(dataptr dz,aplptr ap)
  401. {
  402. int n, m; /* PARAMS */
  403. for(n=0;n<ap->max_param_cnt;n++) {
  404. switch(ap->param_list[n]) {
  405. case('0'): break; /* dz->is_active[n] = 0 is default */
  406. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  407. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  408. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  409. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  410. default:
  411. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  412. return(PROGRAM_ERROR);
  413. }
  414. } /* OPTIONS */
  415. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  416. switch(ap->option_list[n]) {
  417. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  418. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  419. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  420. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  421. default:
  422. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  423. return(PROGRAM_ERROR);
  424. }
  425. } /* VARIANTS */
  426. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  427. switch(ap->variant_list[n]) {
  428. case('0'): break;
  429. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  430. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  431. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  432. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  433. default:
  434. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  435. return(PROGRAM_ERROR);
  436. }
  437. } /* INTERNAL */
  438. for(n=0,
  439. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  440. switch(ap->internal_param_list[n]) {
  441. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  442. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  443. case('d'): dz->no_brk[m] = (char)1; break;
  444. default:
  445. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  446. return(PROGRAM_ERROR);
  447. }
  448. }
  449. return(FINISHED);
  450. }
  451. /************************ HANDLE_THE_OUTFILE *********************/
  452. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
  453. {
  454. char *filename = (*cmdline)[0], *p;
  455. if(filename[0]=='-' && filename[1]=='f') {
  456. dz->floatsam_output = 1;
  457. dz->true_outfile_stype = SAMP_FLOAT;
  458. filename+= 2;
  459. }
  460. if(!sloom) {
  461. if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
  462. sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
  463. return(DATA_ERROR);
  464. }
  465. }
  466. p = filename; // Drop file extension
  467. while(*p != ENDOFSTR) {
  468. if(*p == '.') {
  469. *p = ENDOFSTR;
  470. break;
  471. }
  472. p++;
  473. }
  474. strcpy(dz->outfilename,filename);
  475. (*cmdline)++;
  476. (*cmdlinecnt)--;
  477. return(FINISHED);
  478. }
  479. /************************ OPEN_THE_OUTFILE *********************/
  480. int open_the_outfile(char *sfnam,dataptr dz)
  481. {
  482. int exit_status;
  483. if(!sloom && dz->mode == 1)
  484. strcat(sfnam,"0");
  485. if((exit_status = create_sized_outfile(sfnam,dz))<0)
  486. return(exit_status);
  487. return(FINISHED);
  488. }
  489. /***************************** ESTABLISH_APPLICATION **************************/
  490. int establish_application(dataptr dz)
  491. {
  492. aplptr ap;
  493. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  494. sprintf(errstr,"establish_application()\n");
  495. return(MEMORY_ERROR);
  496. }
  497. ap = dz->application;
  498. memset((char *)ap,0,sizeof(struct applic));
  499. return(FINISHED);
  500. }
  501. /************************* INITIALISE_VFLAGS *************************/
  502. int initialise_vflags(dataptr dz)
  503. {
  504. int n;
  505. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  506. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  507. return(MEMORY_ERROR);
  508. }
  509. for(n=0;n<dz->application->vflag_cnt;n++)
  510. dz->vflag[n] = FALSE;
  511. return FINISHED;
  512. }
  513. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  514. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  515. {
  516. int n;
  517. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  518. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  519. return(MEMORY_ERROR);
  520. }
  521. for(n=0;n<tipc;n++)
  522. ap->default_val[n] = 0.0;
  523. return(FINISHED);
  524. }
  525. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  526. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  527. {
  528. int n;
  529. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  530. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  531. return(MEMORY_ERROR);
  532. }
  533. for(n=0;n<tipc;n++)
  534. dz->is_active[n] = (char)0;
  535. return(FINISHED);
  536. }
  537. /************************* SETUP_STRANDS_APPLICATION *******************/
  538. int setup_strands_application(dataptr dz)
  539. {
  540. int exit_status;
  541. aplptr ap;
  542. if((exit_status = establish_application(dz))<0) // GLOBAL
  543. return(FAILED);
  544. ap = dz->application;
  545. // SEE parstruct FOR EXPLANATION of next 2 functions
  546. if(dz->mode == 2) {
  547. if((exit_status = set_param_data(ap,COUTHREADS,14,13,"di0dddDDDDDDDi"))<0)
  548. return(FAILED);
  549. } else {
  550. if((exit_status = set_param_data(ap,0,14,14,"diidddDDDDDDDi"))<0)
  551. return(FAILED);
  552. }
  553. if(dz->mode == 0 || dz->mode == 2) {
  554. if((exit_status = set_vflgs(ap,"gmf",3,"ddi","",0,0,""))<0)
  555. return(exit_status);
  556. } else {
  557. if((exit_status = set_vflgs(ap,"gmf",3,"ddi","s",1,0,"0"))<0)
  558. return(exit_status);
  559. }
  560. dz->input_data_type = NO_FILE_AT_ALL;
  561. switch(dz->mode) {
  562. case(0):
  563. case(2):
  564. dz->process_type = TO_TEXTFILE;
  565. dz->outfiletype = TEXTFILE_OUT;
  566. break;
  567. case(1):
  568. dz->process_type = UNEQUAL_SNDFILE;
  569. dz->outfiletype = SNDFILE_OUT;
  570. break;
  571. }
  572. // set_legal_infile_structure -->
  573. dz->has_otherfile = FALSE;
  574. // assign_process_logic -->
  575. return application_init(dz); //GLOBAL
  576. }
  577. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  578. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  579. {
  580. int exit_status;
  581. infileptr infile_info;
  582. if(!sloom) {
  583. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  584. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  585. return(MEMORY_ERROR);
  586. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  587. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  588. return(PROGRAM_ERROR);
  589. } else if(infile_info->filetype != SNDFILE) {
  590. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  591. return(DATA_ERROR);
  592. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  593. sprintf(errstr,"Failed to copy file parsing information\n");
  594. return(PROGRAM_ERROR);
  595. }
  596. free(infile_info);
  597. }
  598. return(FINISHED);
  599. }
  600. /************************* SETUP_STRANDS_PARAM_RANGES_AND_DEFAULTS *******************/
  601. int setup_strands_param_ranges_and_defaults(dataptr dz)
  602. {
  603. int exit_status;
  604. aplptr ap = dz->application;
  605. // set_param_ranges()
  606. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  607. // NB total_input_param_cnt is > 0 !!!
  608. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  609. return(FAILED);
  610. // get_param_ranges()
  611. ap->lo[STRAND_DUR] = 0.0;
  612. ap->hi[STRAND_DUR] = 32767.0;
  613. ap->default_val[STRAND_DUR] = 10.0;
  614. ap->lo[STRAND_BANDS] = 1;
  615. ap->hi[STRAND_BANDS] = 16;
  616. ap->default_val[STRAND_BANDS] = 4;
  617. if(dz->mode != 2) {
  618. ap->lo[STRAND_THRDS] = 2;
  619. ap->hi[STRAND_THRDS] = 100;
  620. ap->default_val[STRAND_THRDS] = 3;
  621. }
  622. ap->lo[STRAND_TSTEP] = 1;
  623. ap->hi[STRAND_TSTEP] = 500;
  624. ap->default_val[STRAND_TSTEP] = 100;
  625. ap->lo[STRAND_BOT] = 0;
  626. ap->hi[STRAND_BOT] = 127;
  627. ap->default_val[STRAND_BOT] = 36;
  628. ap->lo[STRAND_TOP] = 0;
  629. ap->hi[STRAND_TOP] = 127;
  630. ap->default_val[STRAND_TOP] = 84;
  631. ap->lo[STRAND_TWIST] = 0;
  632. ap->hi[STRAND_TWIST] = 10;
  633. ap->default_val[STRAND_TWIST] = 3;
  634. ap->lo[STRAND_RAND] = 0;
  635. ap->hi[STRAND_RAND] = 1;
  636. ap->default_val[STRAND_RAND] = 0;
  637. ap->lo[STRAND_SCAT] = 0;
  638. ap->hi[STRAND_SCAT] = 1;
  639. ap->default_val[STRAND_SCAT] = 0;
  640. ap->lo[STRAND_VAMP] = 0;
  641. ap->hi[STRAND_VAMP] = 1;
  642. ap->default_val[STRAND_VAMP] = 0;
  643. ap->lo[STRAND_VMIN] = 0;
  644. ap->hi[STRAND_VMIN] = 4;
  645. ap->default_val[STRAND_VMIN] = 0;
  646. ap->lo[STRAND_VMAX] = 0;
  647. ap->hi[STRAND_VMAX] = 4;
  648. ap->default_val[STRAND_VMAX] = 0;
  649. ap->lo[STRAND_TURB] = 0;
  650. ap->hi[STRAND_TURB] = 2;
  651. ap->default_val[STRAND_TURB] = 0;
  652. ap->lo[STRAND_SEED] = 0;
  653. ap->hi[STRAND_SEED] = 256;
  654. ap->default_val[STRAND_SEED] = 0;
  655. ap->lo[STRAND_GAP] = 0;
  656. ap->hi[STRAND_GAP] = 12;
  657. ap->default_val[STRAND_GAP] = 0;
  658. ap->lo[STRAND_MINB] = 1;
  659. ap->hi[STRAND_MINB] = 24;
  660. ap->default_val[STRAND_MINB] = 12;
  661. ap->lo[STRAND_3D] = -1;
  662. ap->hi[STRAND_3D] = 1;
  663. ap->default_val[STRAND_3D] = 0;
  664. dz->maxmode = 3;
  665. if(!sloom)
  666. put_default_vals_in_all_params(dz);
  667. return(FINISHED);
  668. }
  669. /********************************* PARSE_SLOOM_DATA *********************************/
  670. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  671. {
  672. int exit_status;
  673. int cnt = 1, infilecnt;
  674. int filesize, insams, inbrksize;
  675. double dummy;
  676. int true_cnt = 0;
  677. aplptr ap;
  678. while(cnt<=PRE_CMDLINE_DATACNT) {
  679. if(cnt > argc) {
  680. sprintf(errstr,"Insufficient data sent from TK\n");
  681. return(DATA_ERROR);
  682. }
  683. switch(cnt) {
  684. case(1):
  685. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  686. sprintf(errstr,"Cannot read process no. sent from TK\n");
  687. return(DATA_ERROR);
  688. }
  689. break;
  690. case(2):
  691. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  692. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  693. return(DATA_ERROR);
  694. }
  695. if(dz->mode > 0)
  696. dz->mode--;
  697. //setup_particular_application() =
  698. if((exit_status = setup_strands_application(dz))<0)
  699. return(exit_status);
  700. ap = dz->application;
  701. break;
  702. case(3):
  703. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  704. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  705. return(DATA_ERROR);
  706. }
  707. if(infilecnt < 1) {
  708. true_cnt = cnt + 1;
  709. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  710. }
  711. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  712. return(exit_status);
  713. break;
  714. case(INPUT_FILETYPE+4):
  715. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  716. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  717. return(DATA_ERROR);
  718. }
  719. break;
  720. case(INPUT_FILESIZE+4):
  721. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  722. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  723. return(DATA_ERROR);
  724. }
  725. dz->insams[0] = filesize;
  726. break;
  727. case(INPUT_INSAMS+4):
  728. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  729. sprintf(errstr,"Cannot read insams sent from TK\n");
  730. return(DATA_ERROR);
  731. }
  732. dz->insams[0] = insams;
  733. break;
  734. case(INPUT_SRATE+4):
  735. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  736. sprintf(errstr,"Cannot read srate sent from TK\n");
  737. return(DATA_ERROR);
  738. }
  739. break;
  740. case(INPUT_CHANNELS+4):
  741. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  742. sprintf(errstr,"Cannot read channels sent from TK\n");
  743. return(DATA_ERROR);
  744. }
  745. break;
  746. case(INPUT_STYPE+4):
  747. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  748. sprintf(errstr,"Cannot read stype sent from TK\n");
  749. return(DATA_ERROR);
  750. }
  751. break;
  752. case(INPUT_ORIGSTYPE+4):
  753. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  754. sprintf(errstr,"Cannot read origstype sent from TK\n");
  755. return(DATA_ERROR);
  756. }
  757. break;
  758. case(INPUT_ORIGRATE+4):
  759. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  760. sprintf(errstr,"Cannot read origrate sent from TK\n");
  761. return(DATA_ERROR);
  762. }
  763. break;
  764. case(INPUT_MLEN+4):
  765. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  766. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  767. return(DATA_ERROR);
  768. }
  769. break;
  770. case(INPUT_DFAC+4):
  771. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  772. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  773. return(DATA_ERROR);
  774. }
  775. break;
  776. case(INPUT_ORIGCHANS+4):
  777. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  778. sprintf(errstr,"Cannot read origchans sent from TK\n");
  779. return(DATA_ERROR);
  780. }
  781. break;
  782. case(INPUT_SPECENVCNT+4):
  783. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  784. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  785. return(DATA_ERROR);
  786. }
  787. dz->specenvcnt = dz->infile->specenvcnt;
  788. break;
  789. case(INPUT_WANTED+4):
  790. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  791. sprintf(errstr,"Cannot read wanted sent from TK\n");
  792. return(DATA_ERROR);
  793. }
  794. break;
  795. case(INPUT_WLENGTH+4):
  796. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  797. sprintf(errstr,"Cannot read wlength sent from TK\n");
  798. return(DATA_ERROR);
  799. }
  800. break;
  801. case(INPUT_OUT_CHANS+4):
  802. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  803. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  804. return(DATA_ERROR);
  805. }
  806. break;
  807. /* RWD these chanegs to samps - tk will have to deal with that! */
  808. case(INPUT_DESCRIPTOR_BYTES+4):
  809. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  810. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  811. return(DATA_ERROR);
  812. }
  813. break;
  814. case(INPUT_IS_TRANSPOS+4):
  815. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  816. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  817. return(DATA_ERROR);
  818. }
  819. break;
  820. case(INPUT_COULD_BE_TRANSPOS+4):
  821. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  822. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  823. return(DATA_ERROR);
  824. }
  825. break;
  826. case(INPUT_COULD_BE_PITCH+4):
  827. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  828. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  829. return(DATA_ERROR);
  830. }
  831. break;
  832. case(INPUT_DIFFERENT_SRATES+4):
  833. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  834. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  835. return(DATA_ERROR);
  836. }
  837. break;
  838. case(INPUT_DUPLICATE_SNDS+4):
  839. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  840. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  841. return(DATA_ERROR);
  842. }
  843. break;
  844. case(INPUT_BRKSIZE+4):
  845. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  846. sprintf(errstr,"Cannot read brksize sent from TK\n");
  847. return(DATA_ERROR);
  848. }
  849. if(inbrksize > 0) {
  850. switch(dz->input_data_type) {
  851. case(WORDLIST_ONLY):
  852. break;
  853. case(PITCH_AND_PITCH):
  854. case(PITCH_AND_TRANSPOS):
  855. case(TRANSPOS_AND_TRANSPOS):
  856. dz->tempsize = inbrksize;
  857. break;
  858. case(BRKFILES_ONLY):
  859. case(UNRANGED_BRKFILE_ONLY):
  860. case(DB_BRKFILES_ONLY):
  861. case(ALL_FILES):
  862. case(ANY_NUMBER_OF_ANY_FILES):
  863. if(dz->extrabrkno < 0) {
  864. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  865. return(DATA_ERROR);
  866. }
  867. if(dz->brksize == NULL) {
  868. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  869. return(PROGRAM_ERROR);
  870. }
  871. dz->brksize[dz->extrabrkno] = inbrksize;
  872. break;
  873. default:
  874. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  875. dz->input_data_type);
  876. return(PROGRAM_ERROR);
  877. }
  878. break;
  879. }
  880. break;
  881. case(INPUT_NUMSIZE+4):
  882. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  883. sprintf(errstr,"Cannot read numsize sent from TK\n");
  884. return(DATA_ERROR);
  885. }
  886. break;
  887. case(INPUT_LINECNT+4):
  888. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  889. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  890. return(DATA_ERROR);
  891. }
  892. break;
  893. case(INPUT_ALL_WORDS+4):
  894. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  895. sprintf(errstr,"Cannot read all_words sent from TK\n");
  896. return(DATA_ERROR);
  897. }
  898. break;
  899. case(INPUT_ARATE+4):
  900. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  901. sprintf(errstr,"Cannot read arate sent from TK\n");
  902. return(DATA_ERROR);
  903. }
  904. break;
  905. case(INPUT_FRAMETIME+4):
  906. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  907. sprintf(errstr,"Cannot read frametime sent from TK\n");
  908. return(DATA_ERROR);
  909. }
  910. dz->frametime = (float)dummy;
  911. break;
  912. case(INPUT_WINDOW_SIZE+4):
  913. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  914. sprintf(errstr,"Cannot read window_size sent from TK\n");
  915. return(DATA_ERROR);
  916. }
  917. break;
  918. case(INPUT_NYQUIST+4):
  919. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  920. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  921. return(DATA_ERROR);
  922. }
  923. break;
  924. case(INPUT_DURATION+4):
  925. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  926. sprintf(errstr,"Cannot read duration sent from TK\n");
  927. return(DATA_ERROR);
  928. }
  929. break;
  930. case(INPUT_MINBRK+4):
  931. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  932. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  933. return(DATA_ERROR);
  934. }
  935. break;
  936. case(INPUT_MAXBRK+4):
  937. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  938. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  939. return(DATA_ERROR);
  940. }
  941. break;
  942. case(INPUT_MINNUM+4):
  943. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  944. sprintf(errstr,"Cannot read minnum sent from TK\n");
  945. return(DATA_ERROR);
  946. }
  947. break;
  948. case(INPUT_MAXNUM+4):
  949. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  950. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  951. return(DATA_ERROR);
  952. }
  953. break;
  954. default:
  955. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  956. return(PROGRAM_ERROR);
  957. }
  958. cnt++;
  959. }
  960. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  961. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  962. return(DATA_ERROR);
  963. }
  964. if(true_cnt)
  965. cnt = true_cnt;
  966. *cmdlinecnt = 0;
  967. while(cnt < argc) {
  968. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  969. return(exit_status);
  970. cnt++;
  971. }
  972. return(FINISHED);
  973. }
  974. /********************************* GET_TK_CMDLINE_WORD *********************************/
  975. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  976. {
  977. if(*cmdlinecnt==0) {
  978. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  979. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  980. return(MEMORY_ERROR);
  981. }
  982. } else {
  983. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  984. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  985. return(MEMORY_ERROR);
  986. }
  987. }
  988. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  989. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  990. return(MEMORY_ERROR);
  991. }
  992. strcpy((*cmdline)[*cmdlinecnt],q);
  993. (*cmdlinecnt)++;
  994. return(FINISHED);
  995. }
  996. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  997. int assign_file_data_storage(int infilecnt,dataptr dz)
  998. {
  999. int exit_status;
  1000. int no_sndfile_system_files = FALSE;
  1001. dz->infilecnt = infilecnt;
  1002. if((exit_status = allocate_filespace(dz))<0)
  1003. return(exit_status);
  1004. if(no_sndfile_system_files)
  1005. dz->infilecnt = 0;
  1006. return(FINISHED);
  1007. }
  1008. /************************* redundant functions: to ensure libs compile OK *******************/
  1009. int assign_process_logic(dataptr dz)
  1010. {
  1011. return(FINISHED);
  1012. }
  1013. void set_legal_infile_structure(dataptr dz)
  1014. {}
  1015. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  1016. {
  1017. return(FINISHED);
  1018. }
  1019. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1020. {
  1021. return(FINISHED);
  1022. }
  1023. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1024. {
  1025. return(FINISHED);
  1026. }
  1027. int read_special_data(char *str,dataptr dz)
  1028. {
  1029. return(FINISHED);
  1030. }
  1031. int inner_loop
  1032. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1033. {
  1034. return(FINISHED);
  1035. }
  1036. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1037. {
  1038. return(FINISHED);
  1039. }
  1040. /******************************** USAGE1 ********************************/
  1041. int usage1(void)
  1042. {
  1043. usage2("strands");
  1044. return(USAGE_ONLY);
  1045. }
  1046. /********************************************************************************************/
  1047. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1048. {
  1049. if(!strcmp(prog_identifier_from_cmdline,"strands")) dz->process = STRANDS;
  1050. else {
  1051. fprintf(stderr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  1052. return(USAGE_ONLY);
  1053. }
  1054. return(FINISHED);
  1055. }
  1056. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  1057. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  1058. {
  1059. int n;
  1060. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  1061. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  1062. return(MEMORY_ERROR);
  1063. }
  1064. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  1065. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  1066. return(MEMORY_ERROR);
  1067. }
  1068. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1069. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  1070. return(MEMORY_ERROR);
  1071. }
  1072. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1073. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  1074. return(MEMORY_ERROR);
  1075. }
  1076. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1077. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  1078. return(MEMORY_ERROR);
  1079. }
  1080. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1081. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  1082. return(MEMORY_ERROR);
  1083. }
  1084. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1085. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  1086. return(MEMORY_ERROR);
  1087. }
  1088. for(n=0;n<brkcnt;n++) {
  1089. dz->brk[n] = NULL;
  1090. dz->brkptr[n] = NULL;
  1091. dz->brkinit[n] = 0;
  1092. dz->brksize[n] = 0;
  1093. }
  1094. return(FINISHED);
  1095. }
  1096. /******************************** USAGE2 ********************************/
  1097. int usage2(char *str)
  1098. {
  1099. if(!strcmp(str,"strands")) {
  1100. fprintf(stderr,
  1101. "USAGE: strands strands 1 generic_outdatafilename ...\n"
  1102. "OR: strands strands 2 outsndfilename ...\n"
  1103. "dur bands threads tstep bot top twist rand scat vamp vmin vmax turb seed\n"
  1104. "[-ggap] [-mminband] [-f3d] [-s]\n"
  1105. "\n"
  1106. "OR: strands strands 3 generic_outdatafilename ...\n"
  1107. "thrdsfile dur bands tstep bot top twist rand scat vamp vmin vmax turb seed\n"
  1108. "[-ggap] [-mminband] [-f3d] [-s]\n"
  1109. "\n"
  1110. "Generate pitch-data for several streams (or the combined sound itself)\n"
  1111. "where total pitch-tessitura divided into equal-sized pitch-BANDS\n"
  1112. "and each band made of pitch-line THREADS, cycling around one-another\n"
  1113. "pitchwise, within the band, IF twist strays from zero.\n"
  1114. "Strands in adjacent bands spiral in opposite directions.\n"
  1115. "\n"
  1116. "DUR Duration of output data or sound.\n"
  1117. "BANDS Number of bands in the output.\n"
  1118. "THREADS Number of sounds in a band.\n"
  1119. "THRDSFILE Textfile listing number of sounds in EACH band.\n"
  1120. "TSTEP Timestep (in mS) between pitch-data vals in output.\n"
  1121. "BOT Lowest pitch of all output.\n"
  1122. "TOP Highest pitch of all output.\n"
  1123. "TWIST Rate of cycling of output pitches in bands (Hz).\n"
  1124. "RAND Random variation of twist frq from band to band.\n"
  1125. "SCAT Random-warp of cycles of threads in same band.\n"
  1126. "VORTEX WAVINESS\n"
  1127. "VAMP ammount band-boundaries wander from fixed frqs.\n"
  1128. "VMIN min rate of oscillation of band boundaries.\n"
  1129. "VMAX max rate of oscillation of band boundaries.\n"
  1130. "TURBULENCE\n"
  1131. "TURB 0 none: >0-to-1 turbulence in bands: >1-to-2 gobal turbulence.\n"
  1132. "SEED Seed value for randomisation settings.\n"
  1133. "GAP Minimum pitch-gap between bands.\n"
  1134. "MINBAND Minimum pitchwidth of any band.\n"
  1135. "3D Motion in 3D: 0 = none: 1 = bottom band up at front: -1 = down.\n"
  1136. "\n"
  1137. "-s (Mode 2 only) - outputs each band in succesion.\n"
  1138. "\n"
  1139. "Press any key to see further information.\n");
  1140. while(!kbhit())
  1141. ;
  1142. if(kbhit()) {
  1143. fprintf(stderr,
  1144. "\n"
  1145. "TWIST & With twist ZERO, streams do not cycle round one another\n"
  1146. "LAMINAR but stay at steady(ish) pitches .. (\"laminar flow\").\n"
  1147. "FLOW To force laminar flow, use 2 adjacent brkpnt vals of zero\n"
  1148. " (laminar flow is forced between the associated times).\n"
  1149. " To move to twisted flow, follow a zero val by a non-zero val.\n"
  1150. " To maintain twisted flow, follow non-zero val by non-zero val.\n"
  1151. " To untwist the flow, follow a non-zero val by a zero val.\n"
  1152. " \n"
  1153. " During laminar flow,\n"
  1154. " \"RAND\" controls pitch-jitter of laminae.\n"
  1155. " \"SCAT\" controls level-jitter of laminae.\n"
  1156. " \n"
  1157. "3D Outputs 2 extra param sets for each stream.\n"
  1158. " 1st set can control loudness, or synth partial-cnt\n"
  1159. " in creation of a synthesized output.\n"
  1160. " 2nd set can control a mix with reverb (etc) version,\n"
  1161. " (parameter is level of modified source in that mix)\n"
  1162. " both to simulate distance from the listener.\n"
  1163. " In modes 1 & 3, this extra data is output in separate files\n"
  1164. " AFTER all the pitchdata files have been output.\n"
  1165. " The output order is ...\n"
  1166. " all pitch data, all 1st controlfiles, all 2nd controlfiles.\n"
  1167. "\n"
  1168. "TURBULENT This can only happen (turb > 0.0) when twist > 0.0\n"
  1169. "FLOW (i.e. there can be no turbulence during laminar flow\n"
  1170. " or in the transitions to and from twisted flow).\n"
  1171. "\n"
  1172. "MODE 2 SOUND OUTPUT\n"
  1173. " Intended only as sound-test for the data output in mode 1.\n"
  1174. " Bands are output, equally spaced, across the stereo stage.\n"
  1175. "\n");
  1176. }
  1177. } else
  1178. fprintf(stdout,"Unknown option '%s'\n",str);
  1179. return(USAGE_ONLY);
  1180. }
  1181. int usage3(char *str1,char *str2)
  1182. {
  1183. fprintf(stderr,"Insufficient parameters on command line.\n");
  1184. return(USAGE_ONLY);
  1185. }
  1186. /**************************** STRANDS_PARAM_PREPROCESS *************************
  1187. *
  1188. * Arrays 0 to N-1 store the stream frq information at each timestep.
  1189. * Array N stores the simetable.
  1190. * Array N+1 store sintable-pointer values for each stream being synthesized.
  1191. */
  1192. int strands_param_preprocess(double *pitchrange,double *band_separation,double *tessitura,int *isturb,int threadvalscnt,dataptr dz)
  1193. {
  1194. int exit_status, synth_arrays = 0, rotation_arrays = 0, universal_arrays;
  1195. int n;
  1196. double srate, endsplice, gaps;
  1197. double *sintab, *costab;
  1198. // Setup global params
  1199. dz->param[STRAND_TSTEP] *= MS_TO_SECS;
  1200. dz->datasize = (int)ceil(dz->param[STRAND_DUR]/dz->param[STRAND_TSTEP]) + 1; // Size of data output depends on timestep used
  1201. if(dz->mode == 2) {
  1202. if(threadvalscnt != dz->iparam[STRAND_BANDS]) {
  1203. sprintf(errstr,"NUMBER OF THREAD COUNTS in data file (%d) does not tally with band count (%d).\n",threadvalscnt,dz->iparam[STRAND_BANDS]);
  1204. return(MEMORY_ERROR);
  1205. }
  1206. dz->itemcnt = 0;
  1207. for(n=0;n<dz->iparam[STRAND_BANDS];n++)
  1208. dz->itemcnt += dz->iparray[0][n];
  1209. } else
  1210. dz->itemcnt = dz->iparam[STRAND_THRDS] * dz->iparam[STRAND_BANDS]; // No of threads in output
  1211. dz->scalefact = (double)SYNTH_TABSIZE/(double)STRAND_SRATE; // Scales reading of sintab to sound-output samplerate
  1212. dz->scaler = (double)SYNTH_TABSIZE * dz->param[STRAND_TSTEP]; // Scales reading of sintab to output-data "sample-rate"
  1213. // Setup effective bandwidths
  1214. *pitchrange = dz->param[STRAND_TOP] - dz->param[STRAND_BOT]; // Total pitchrange used
  1215. if(*pitchrange <= 0) {
  1216. sprintf(errstr,"Invalid pitch range (<= 0.0).\n");
  1217. return(DATA_ERROR);
  1218. }
  1219. *band_separation = *pitchrange/(double)dz->param[STRAND_BANDS]; // Separation is distance between bands (prior to any gapping)
  1220. gaps = dz->param[STRAND_GAP] * (dz->param[STRAND_BANDS] - 1);
  1221. if(*pitchrange - gaps <= 0.0) {
  1222. sprintf(errstr,"Pitch range (%lf) incompatible with band gaps (totalling %lf).\n",*pitchrange,gaps);
  1223. return(DATA_ERROR);
  1224. }
  1225. *tessitura = *pitchrange - gaps;
  1226. *tessitura /= dz->param[STRAND_BANDS]; // Tessitura is actual width of bands, after gapping
  1227. if(*tessitura < dz->param[STRAND_MINB]) { // (and before any wavy-banding distortion)
  1228. if(gaps > 0.0) {
  1229. sprintf(errstr,"Pitch range of a band (%lf) incompatible with min bandwidth and band gaps.\n",*tessitura);
  1230. return(DATA_ERROR);
  1231. } else {
  1232. sprintf(errstr,"Pitch range of a band (%lf) incompatible with minimum bandwidth (%lf).\n",*tessitura,dz->param[STRAND_MINB]);
  1233. return(DATA_ERROR);
  1234. }
  1235. }
  1236. // ESTABLISH ARRAYS AS FOLLOWS
  1237. // List of frqs, at specific times, in each strand (dz->itemcnt)
  1238. // Sin table (1)
  1239. // Cos table (1)
  1240. // Pointers into sinetable for each strand (1)
  1241. // Table to store FLOW-TYPES (1)
  1242. universal_arrays = dz->itemcnt + 4;
  1243. // SYNTHESIS ALSO NEEDS....
  1244. // 2nd-derivs of frqdata for each strand, for cubic splining (dz->itemcnt)
  1245. synth_arrays = dz->itemcnt;
  1246. // If 3D, outputs level data
  1247. // List of levels, at specific times, in each strand (dz->itemcnt)
  1248. // 2nd-derivs of leveldata for each strand, for cubic splining (dz->itemcnt)
  1249. rotation_arrays = dz->itemcnt * 2;
  1250. if((dz->parray = (double **)malloc((universal_arrays+synth_arrays+rotation_arrays) * sizeof(double *)))==NULL) {
  1251. sprintf(errstr,"INSUFFICIENT MEMORY for data storage.\n");
  1252. return(MEMORY_ERROR);
  1253. }
  1254. // Storage of stream pitch-data
  1255. for(n=0;n<dz->itemcnt;n++) {
  1256. if((dz->parray[n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
  1257. sprintf(errstr,"INSUFFICIENT MEMORY for stream-data %d storage and beyond.\n",n+1);
  1258. return(MEMORY_ERROR);
  1259. }
  1260. } // pitches AAAAAAA
  1261. dz->sintable = dz->itemcnt; // +sintab AAAAAAA B
  1262. dz->costable = dz->itemcnt + 1; // +sintab AAAAAAA BC
  1263. dz->sinptrs = dz->itemcnt + 2; // +sinptrs AAAAAAA BCD
  1264. dz->flowdata = dz->itemcnt + 3; // +flowtpye AAAAAAA BCDE
  1265. dz->rotlevel = dz->itemcnt + 4; // +rotlevel AAAAAAA BCDE FFFFFFF
  1266. dz->rotmix = dz->rotlevel; // Used by different modes, (and for info only as variables defined as equivalent)
  1267. dz->derivs = dz->rotlevel + dz->itemcnt; // +levderivs AAAAAAA BCDE FFFFFFF GGGGGGG
  1268. dz->levderivs = dz->rotlevel + dz->itemcnt; // +levderivs AAAAAAA BCDE FFFFFFF GGGGGGG HHHHHHH
  1269. // Establish sinetable: fixed size
  1270. if((dz->parray[dz->sintable] = (double *)malloc((SYNTH_TABSIZE +1) * sizeof(double)))==NULL) {
  1271. sprintf(errstr,"INSUFFICIENT MEMORY for sine table.\n");
  1272. return(MEMORY_ERROR);
  1273. }
  1274. sintab = dz->parray[dz->sintable];
  1275. for(n=0;n<SYNTH_TABSIZE;n++)
  1276. sintab[n] = sin(PI * 2.0 * ((double)n/(double)SYNTH_TABSIZE));
  1277. sintab[n] = sintab[0]; /* wrap around point */
  1278. // Establish inverted cosine table: fixed size
  1279. if((dz->parray[dz->costable] = (double *)malloc((SYNTH_TABSIZE +1) * sizeof(double)))==NULL) {
  1280. sprintf(errstr,"INSUFFICIENT MEMORY for cosin table.\n");
  1281. return(MEMORY_ERROR);
  1282. }
  1283. costab = dz->parray[dz->costable];
  1284. for(n=0;n<SYNTH_TABSIZE;n++)
  1285. costab[n] = -cos(PI * 2.0 * ((double)n/(double)SYNTH_TABSIZE));
  1286. costab[n] = costab[0]; /* wrap around point */
  1287. // Establish sine-table pointers: one for each stream
  1288. if((dz->parray[dz->sinptrs] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1289. sprintf(errstr,"INSUFFICIENT MEMORY for strand sintable pointers.\n");
  1290. return(MEMORY_ERROR);
  1291. }
  1292. // If streams rotate in radial direction, establish arrays to store relative-level-data, +-90 out of phase with pitch motion
  1293. if(dz->iparam[STRAND_3D]) {
  1294. for(n=0;n<dz->itemcnt;n++) {
  1295. if((dz->parray[dz->rotlevel+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
  1296. sprintf(errstr,"INSUFFICIENT MEMORY for storing radial motion data %d and beyond.\n",n+1);
  1297. return(MEMORY_ERROR);
  1298. }
  1299. }
  1300. }
  1301. // If sound is to be synthesized
  1302. if(dz->mode == 1) {
  1303. // establish 2nd derivative arrays, for cubic spline interpolation
  1304. for(n=0;n<dz->itemcnt;n++) {
  1305. if((dz->parray[dz->derivs+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
  1306. sprintf(errstr,"INSUFFICIENT MEMORY for storing stream-data cubic-spline slope %d and beyond.\n",n+1);
  1307. return(MEMORY_ERROR);
  1308. }
  1309. }
  1310. if(dz->iparam[STRAND_3D]) {
  1311. for(n=0;n<dz->itemcnt;n++) {
  1312. if((dz->parray[dz->levderivs+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
  1313. sprintf(errstr,"INSUFFICIENT MEMORY for storing radial motion level cubic-spline slope %d and beyond.\n",n+1);
  1314. return(MEMORY_ERROR);
  1315. }
  1316. }
  1317. }
  1318. // Establish output length in samples
  1319. srate = (double)dz->infile->srate;
  1320. dz->iparam[STRAND_DUR] = (int)round(dz->param[STRAND_DUR] * srate) * dz->infile->channels;
  1321. // Establish end splice length
  1322. endsplice = 50.0 * MS_TO_SECS; // Go for big splice
  1323. if(dz->param[STRAND_DUR] <= endsplice * 2)
  1324. endsplice = min(dz->param[STRAND_DUR]/4.0,5.0 * MS_TO_SECS); // Else go for small splice
  1325. dz->splicesize = (int)floor(endsplice * srate); // Establish size of final splice
  1326. } else {
  1327. if(dz->iparam[STRAND_3D]) {
  1328. // 2nd set of control data files, 180 or 0 out of phase with pitch motion
  1329. for(n=0;n<dz->itemcnt;n++) {
  1330. if((dz->parray[dz->rotmix+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
  1331. sprintf(errstr,"INSUFFICIENT MEMORY for storing 2nd radial motion data %d and beyond.\n",n+1);
  1332. return(MEMORY_ERROR);
  1333. }
  1334. }
  1335. }
  1336. }
  1337. // Determine where flow is laminar, or banded, and where it transits between the two
  1338. if((exit_status = establish_flow_types(dz))<0)
  1339. return exit_status;
  1340. // Check turbulence parameter is consistent with physical model
  1341. if((exit_status = check_turbulence_values(isturb,dz))<0)
  1342. return exit_status;
  1343. return(FINISHED);
  1344. }
  1345. /******************************** SYNTHESIS *********************************/
  1346. int synthesis(dataptr dz)
  1347. {
  1348. int exit_status, n, m, cycend = 0, getlevel = 1, bandno, chans = dz->infile->channels;
  1349. int inendsplice, instartsplice;
  1350. int totaloutsamps, sampcnt = 0, startspliceend = dz->splicesize * chans, outsamps_generated, xxtempsize;
  1351. int endsplicestart = dz->iparam[STRAND_DUR] - (dz->splicesize * chans), threadbas;
  1352. double val, maxval = 1.0, srate = (double)dz->infile->srate, time = 0.0, spliceincr, spliceval, normaliser;
  1353. double level, thispitch, thisfrq, pos = -1.0, posstep;
  1354. float *obuf = dz->sampbuf[0];
  1355. double *sinptr = dz->parray[dz->sinptrs], *llev, *rlev;
  1356. // NB This assumes data has been generated, in 1st dz->itemcnt parrays
  1357. dz->tempsize = dz->iparam[STRAND_DUR];
  1358. if((llev = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1359. sprintf(errstr,"INSUFFICIENT MEMORY for storing left levels of stereo output.\n");
  1360. return(MEMORY_ERROR);
  1361. }
  1362. if((rlev = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1363. sprintf(errstr,"INSUFFICIENT MEMORY for storing right levels of stereo output.\n");
  1364. return(MEMORY_ERROR);
  1365. }
  1366. posstep = 2.0/(double)(dz->iparam[STRAND_BANDS] - 1);
  1367. bandno = 0;
  1368. for(n= 0; n < dz->itemcnt;n++) {
  1369. if((exit_status = spline(n,0,dz))<0) // Establish array of 2nd derivs for cubic spline interp of FRQ values
  1370. return exit_status;
  1371. if(n % dz->iparam[STRAND_THRDS] == 0) { // Establish stere-positioning levels for L+R chann outputs, for each stream
  1372. pancalc(pos,&(llev[bandno]),&(rlev[bandno]));
  1373. pos += posstep;
  1374. bandno++;
  1375. }
  1376. }
  1377. if(dz->iparam[STRAND_3D]) {
  1378. for(n= 0; n< dz->itemcnt;n++) {
  1379. if((exit_status = spline(n,getlevel,dz))<0) // Establish array of 2nd derivs for cubic spline interp of LEVEL values
  1380. return exit_status;
  1381. }
  1382. }
  1383. spliceincr = 1.0/(double)dz->splicesize;
  1384. spliceval = 0.0;
  1385. instartsplice = 1;
  1386. inendsplice = 0;
  1387. totaloutsamps = dz->iparam[STRAND_DUR];
  1388. fprintf(stdout,"INFO: First pass: assessing synthesis level.\n");
  1389. fflush(stdout);
  1390. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1391. for(n=0;n<dz->itemcnt;n++) // Zero sine-table pointers for all streams
  1392. sinptr[n] = 0.0;
  1393. outsamps_generated = 0;
  1394. if(dz->vflag[0]) {
  1395. for(bandno = 0; bandno < dz->iparam[STRAND_BANDS];bandno++) {
  1396. instartsplice = 1;
  1397. inendsplice = 0;
  1398. fprintf(stdout,"INFO: Band %d\n",bandno+1);
  1399. fflush(stdout);
  1400. threadbas = bandno * dz->iparam[STRAND_THRDS];
  1401. outsamps_generated = 0;
  1402. while(outsamps_generated < totaloutsamps) {
  1403. time = (double)outsamps_generated/chans/srate;
  1404. for(m=0,n=threadbas;m<dz->iparam[STRAND_THRDS];n++,m++) {
  1405. thispitch = splint(n,time,0,dz); // Pitch read by cubic-splining between generated values in data output
  1406. thisfrq = miditohz(thispitch);
  1407. val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
  1408. // Use frq to read sinetable, using tabpointer for specific stream
  1409. if(dz->iparam[STRAND_3D]) {
  1410. level = splint(n,time,getlevel,dz); // Read corresponding level
  1411. val *= level;
  1412. }
  1413. obuf[sampcnt] = (float)(obuf[sampcnt] + (val * llev[bandno]));
  1414. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * rlev[bandno]));
  1415. }
  1416. if(instartsplice) {
  1417. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1418. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1419. spliceval += spliceincr;
  1420. spliceval = min(spliceval,1.0);
  1421. } else if(inendsplice) {
  1422. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1423. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1424. spliceval -= spliceincr;
  1425. spliceval = max(spliceval,0.0);
  1426. }
  1427. maxval = max(maxval,fabs(obuf[sampcnt]));
  1428. maxval = max(maxval,fabs(obuf[sampcnt+1]));
  1429. if((sampcnt+=2) >= dz->buflen) {
  1430. dz->process = GREV;
  1431. dz->total_samps_written = outsamps_generated;
  1432. xxtempsize = dz->tempsize;
  1433. dz->tempsize *= dz->iparam[STRAND_BANDS];
  1434. display_virtual_time(dz->total_samps_written,dz);
  1435. dz->tempsize = xxtempsize;
  1436. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1437. sampcnt = 0;
  1438. }
  1439. outsamps_generated += 2;
  1440. if(!inendsplice && (outsamps_generated >= endsplicestart)) {
  1441. inendsplice = 1;
  1442. spliceval = 1.0;
  1443. }
  1444. if(instartsplice && (outsamps_generated >= startspliceend))
  1445. instartsplice = 0;
  1446. }
  1447. dz->process = GREV;
  1448. dz->total_samps_written = outsamps_generated;
  1449. display_virtual_time(dz->total_samps_written,dz);
  1450. dz->process = STRANDS;
  1451. }
  1452. } else {
  1453. while(outsamps_generated < totaloutsamps) {
  1454. time = (double)outsamps_generated/chans/srate;
  1455. for(n=0;n<dz->itemcnt;n++) {
  1456. bandno = n/dz->iparam[STRAND_THRDS];
  1457. thispitch = splint(n,time,0,dz); // Pitch read by cubic-splining between generated values in data output
  1458. thisfrq = miditohz(thispitch);
  1459. val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
  1460. // Use frq to read sinetable, using tabpointer for specific stream
  1461. if(dz->iparam[STRAND_3D]) {
  1462. level = splint(n,time,getlevel,dz); // Read corresponding level
  1463. val *= level;
  1464. }
  1465. obuf[sampcnt] = (float)(obuf[sampcnt] + (val * llev[bandno]));
  1466. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * rlev[bandno]));
  1467. }
  1468. if(instartsplice) {
  1469. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1470. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1471. spliceval += spliceincr;
  1472. spliceval = min(spliceval,1.0);
  1473. } else if(inendsplice) {
  1474. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1475. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1476. spliceval -= spliceincr;
  1477. spliceval = max(spliceval,0.0);
  1478. }
  1479. maxval = max(maxval,fabs(obuf[sampcnt]));
  1480. maxval = max(maxval,fabs(obuf[sampcnt+1]));
  1481. if((sampcnt+=2) >= dz->buflen) {
  1482. dz->process = GREV;
  1483. dz->total_samps_written = outsamps_generated;
  1484. display_virtual_time(dz->total_samps_written,dz);
  1485. dz->process = STRANDS;
  1486. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1487. sampcnt = 0;
  1488. }
  1489. outsamps_generated += 2;
  1490. if(!inendsplice && (outsamps_generated >= endsplicestart)) {
  1491. inendsplice = 1;
  1492. spliceval = 1.0;
  1493. }
  1494. if(instartsplice && (outsamps_generated >= startspliceend))
  1495. instartsplice = 0;
  1496. }
  1497. dz->process = GREV;
  1498. dz->total_samps_written = outsamps_generated;
  1499. display_virtual_time(dz->total_samps_written,dz);
  1500. dz->process = STRANDS;
  1501. }
  1502. normaliser = 0.85/maxval;
  1503. time = 0.0;
  1504. spliceval = 0.0;
  1505. instartsplice = 1;
  1506. inendsplice = 0;
  1507. dz->total_samps_written = 0;
  1508. outsamps_generated = 0;
  1509. sampcnt = 0;
  1510. for(n=0;n<dz->itemcnt;n++) // Zero sine-table pointers for all streams
  1511. sinptr[n] = 0.0;
  1512. fprintf(stdout,"INFO: Second pass: synthesis.\n");
  1513. fflush(stdout);
  1514. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1515. if(dz->vflag[0]) {
  1516. for(bandno = 0; bandno < dz->iparam[STRAND_BANDS];bandno++) {
  1517. instartsplice = 1;
  1518. inendsplice = 0;
  1519. fprintf(stdout,"INFO: Band %d\n",bandno+1);
  1520. fflush(stdout);
  1521. threadbas = bandno * dz->iparam[STRAND_THRDS];
  1522. outsamps_generated = 0;
  1523. while(outsamps_generated < totaloutsamps) {
  1524. time = (double)outsamps_generated/chans/srate;
  1525. for(m=0,n=threadbas;m<dz->iparam[STRAND_THRDS];n++,m++) {
  1526. thispitch = splint(n,time,0,dz); // Frq read by cubic-splining between generated values in data output
  1527. thisfrq = miditohz(thispitch);
  1528. val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
  1529. // Use frq to read sinetable, using tabpointer for specific stream
  1530. if(dz->iparam[STRAND_3D]) {
  1531. level = splint(n,time,getlevel,dz); // Read corresponding level
  1532. val *= level;
  1533. }
  1534. obuf[sampcnt] = (float)(obuf[sampcnt] + (val * rlev[bandno]));
  1535. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * llev[bandno]));
  1536. if(instartsplice) {
  1537. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1538. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1539. spliceval += spliceincr;
  1540. spliceval = min(spliceval,1.0);
  1541. } else if(inendsplice) {
  1542. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1543. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1544. spliceval -= spliceincr;
  1545. spliceval = max(spliceval,0.0);
  1546. }
  1547. }
  1548. outsamps_generated += 2;
  1549. if(!inendsplice && (outsamps_generated >= endsplicestart)) {
  1550. inendsplice = 1;
  1551. spliceval = 1.0;
  1552. }
  1553. if(instartsplice && (outsamps_generated >= startspliceend))
  1554. instartsplice = 0;
  1555. if((sampcnt+=2) >= dz->buflen) {
  1556. dz->process = GREV;
  1557. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1558. return(exit_status);
  1559. dz->process = STRANDS;
  1560. sampcnt = 0;
  1561. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1562. }
  1563. }
  1564. }
  1565. } else {
  1566. while(outsamps_generated < totaloutsamps) {
  1567. time = (double)outsamps_generated/chans/srate;
  1568. for(n=0;n<dz->itemcnt;n++) {
  1569. bandno = n/dz->iparam[STRAND_THRDS];
  1570. thispitch = splint(n,time,0,dz); // Frq read by cubic-splining between generated values in data output
  1571. thisfrq = miditohz(thispitch);
  1572. val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
  1573. // Use frq to read sinetable, using tabpointer for specific stream
  1574. if(dz->iparam[STRAND_3D]) {
  1575. level = splint(n,time,getlevel,dz); // Read corresponding level
  1576. val *= level;
  1577. }
  1578. obuf[sampcnt] = (float)(obuf[sampcnt] + (val * rlev[bandno]));
  1579. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * llev[bandno]));
  1580. }
  1581. obuf[sampcnt] = (float)(obuf[sampcnt] * normaliser);
  1582. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * normaliser);
  1583. if(instartsplice) {
  1584. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1585. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1586. spliceval += spliceincr;
  1587. spliceval = min(spliceval,1.0);
  1588. } else if(inendsplice) {
  1589. obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
  1590. obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
  1591. spliceval -= spliceincr;
  1592. spliceval = max(spliceval,0.0);
  1593. }
  1594. outsamps_generated += 2;
  1595. if(!inendsplice && (outsamps_generated >= endsplicestart)) {
  1596. inendsplice = 1;
  1597. spliceval = 1.0;
  1598. }
  1599. if(instartsplice && (outsamps_generated >= startspliceend))
  1600. instartsplice = 0;
  1601. if((sampcnt+=2) >= dz->buflen) {
  1602. dz->process = GREV;
  1603. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1604. return(exit_status);
  1605. dz->process = STRANDS;
  1606. sampcnt = 0;
  1607. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1608. }
  1609. }
  1610. }
  1611. if(sampcnt) {
  1612. dz->process = GREV;
  1613. if((exit_status = write_samps(obuf,sampcnt,dz))<0)
  1614. return(exit_status);
  1615. dz->process = STRANDS;
  1616. }
  1617. return FINISHED;
  1618. }
  1619. /**************************** CREATE_STRANDS_SNDBUFS ****************************/
  1620. int create_strands_sndbufs(dataptr dz)
  1621. {
  1622. int n;
  1623. int bigbufsize;
  1624. int framesize;
  1625. framesize = F_SECSIZE;
  1626. dz->bufcnt = 1;
  1627. if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
  1628. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
  1629. return(MEMORY_ERROR);
  1630. }
  1631. if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
  1632. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
  1633. return(MEMORY_ERROR);
  1634. }
  1635. bigbufsize = (int)Malloc(-1);
  1636. bigbufsize /= dz->bufcnt;
  1637. if(bigbufsize <=0)
  1638. bigbufsize = framesize * sizeof(float);
  1639. dz->buflen = bigbufsize / sizeof(float);
  1640. dz->buflen = (dz->buflen / framesize) * framesize;
  1641. bigbufsize = dz->buflen * sizeof(float);
  1642. if((dz->bigbuf = (float *)malloc(bigbufsize * dz->bufcnt)) == NULL) {
  1643. sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
  1644. return(PROGRAM_ERROR);
  1645. }
  1646. for(n=0;n<dz->bufcnt;n++)
  1647. dz->sbufptr[n] = dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
  1648. dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
  1649. return(FINISHED);
  1650. }
  1651. /****************************** GET_THE_MODE_FROM_CMDLINE *********************************/
  1652. int get_the_mode_from_cmdline(char *str,dataptr dz)
  1653. {
  1654. char temp[200], *p;
  1655. if(sscanf(str,"%s",temp)!=1) {
  1656. fprintf(stderr,"Cannot read mode of program.\n");
  1657. return(USAGE_ONLY);
  1658. }
  1659. p = temp + strlen(temp) - 1;
  1660. while(p >= temp) {
  1661. if(!isdigit(*p)) {
  1662. fprintf(stderr,"Invalid mode of program entered.\n");
  1663. return(USAGE_ONLY);
  1664. }
  1665. p--;
  1666. }
  1667. if(sscanf(str,"%d",&dz->mode)!=1) {
  1668. fprintf(stderr,"Cannot read mode of program.\n");
  1669. return(USAGE_ONLY);
  1670. }
  1671. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  1672. fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  1673. return(USAGE_ONLY);
  1674. }
  1675. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  1676. return(FINISHED);
  1677. }
  1678. /**************************** SINREAD *************************/
  1679. double sinread(int iscos,double *tabpos,double frq,int *cycend,double scaling,dataptr dz)
  1680. {
  1681. double tabincr, val, valdiff, timefrac;
  1682. int lopos, hipos;
  1683. double *sintab;
  1684. if(iscos)
  1685. sintab = dz->parray[dz->costable];
  1686. else
  1687. sintab = dz->parray[dz->sintable];
  1688. *cycend = 0;
  1689. lopos = (int)floor(*tabpos);
  1690. hipos = (int)ceil(*tabpos);
  1691. timefrac = *tabpos - (double)lopos;
  1692. val = sintab[lopos];
  1693. valdiff = sintab[hipos] - val;
  1694. val += valdiff * timefrac;
  1695. tabincr = frq * scaling;
  1696. *tabpos += tabincr;
  1697. if(*tabpos >= SYNTH_TABSIZE) {
  1698. *cycend = 1;
  1699. *tabpos -= SYNTH_TABSIZE;
  1700. }
  1701. return val;
  1702. }
  1703. /*************************************** SPLINE *******************************
  1704. *
  1705. * Establish 2nd dervatives table for cubic spline calculations.
  1706. */
  1707. int spline(int streamno,int islevel,dataptr dz)
  1708. {
  1709. double firstderivatzero = 0.0, firstderivatend = 0.0, qn, un, val1, val2; // firstderiveatend is a guess
  1710. double *datatab, *secondderiv, *u;
  1711. int arraysize = dz->datasize;
  1712. int n, t, v, tt, vv, k;
  1713. double thistimestep, thisfrqstep, nexttimestep,nextfrqstep,bigtimestep, lasttime, lastval,sig,p;
  1714. if((u = (double *)malloc(arraysize * sizeof(double)))==NULL) {
  1715. sprintf(errstr,"INSUFFICIENT MEMORY for calculating spline derivatives.\n");
  1716. return(MEMORY_ERROR);
  1717. }
  1718. if(islevel) {
  1719. datatab = dz->parray[dz->rotlevel+streamno]; // The stored level data already calcd for stream "streamno"
  1720. secondderiv = dz->parray[dz->levderivs+streamno];
  1721. } else {
  1722. datatab = dz->parray[streamno]; // The stored frq data already calcd for stream "streamno"
  1723. secondderiv = dz->parray[dz->derivs+streamno];
  1724. }
  1725. secondderiv[0] = -0.5;
  1726. thistimestep = datatab[2] - datatab[0];
  1727. thisfrqstep = datatab[3] - datatab[1];
  1728. val1 = 3.0/thistimestep;
  1729. val2 = (thisfrqstep/thistimestep) - firstderivatzero;
  1730. u[0] = val1 * val2;
  1731. lasttime = datatab[0];
  1732. lastval = datatab[1];
  1733. for(n = 1,t = 2, v = 3, tt = 4, vv = 5; n < arraysize - 1;n++,t+=2,v+=2,tt+=2,vv +=2) { // t indexes current times in brktable, v indexes current values
  1734. thisfrqstep = datatab[v] - lastval; // tt indexes NEXT time, vv indexes NEXT value
  1735. nextfrqstep = datatab[vv] - datatab[v];
  1736. thistimestep = datatab[t] - lasttime;
  1737. nexttimestep = datatab[tt] - datatab[t];
  1738. bigtimestep = datatab[tt] - lasttime;
  1739. sig = thistimestep/bigtimestep;
  1740. p = (sig * secondderiv[n-1]) + 2.0;
  1741. secondderiv[n] = (sig - 1.0)/p;
  1742. u[n] = (nextfrqstep/nexttimestep) - (thisfrqstep/thistimestep);
  1743. u[n] = (6.0 * u[n])/bigtimestep;
  1744. u[n] -= sig * u[n-1];
  1745. u[n] /= p;
  1746. lasttime = datatab[t];
  1747. lastval = datatab[v];
  1748. }
  1749. qn = 0.5;
  1750. thisfrqstep = datatab[v] - lastval;
  1751. thistimestep = datatab[t] - lasttime;
  1752. val1 = 3.0/thistimestep;
  1753. val2 = firstderivatend - (thisfrqstep/thistimestep);
  1754. un = val1 * val2;
  1755. val1 = un - (qn * u[n-1]);
  1756. val2 = (qn * secondderiv[n-1]) + 1.0;
  1757. secondderiv[n] = val1/val2;
  1758. for(k = n-1;k >= 0;k--)
  1759. secondderiv[k] = (secondderiv[k] * secondderiv[k+1]) + u[k];
  1760. return FINISHED;
  1761. }
  1762. /*************************************** SPLINE_LEVEL *******************************
  1763. *
  1764. * Establish 2nd dervatives table for cubic spline calculations.
  1765. */
  1766. int spline_level(int streamno,dataptr dz)
  1767. {
  1768. double firstderivatzero = 0.0, firstderivatend = 0.0, qn, un, val1, val2; // firstderiveatend is a guess
  1769. double *levtab = dz->parray[dz->rotlevel + streamno]; // The stored frq data already calcd for stream "streamno"
  1770. int arraysize = dz->datasize;
  1771. double *secondderiv = dz->parray[dz->levderivs + streamno], *u;
  1772. int n, t, v, tt, vv, k;
  1773. double thistimestep, thisfrqstep, nexttimestep,nextfrqstep,bigtimestep, lasttime, lastval,sig,p;
  1774. if((u = (double *)malloc(arraysize * sizeof(double)))==NULL) {
  1775. sprintf(errstr,"INSUFFICIENT MEMORY for calculating spline derivatives.\n");
  1776. return(MEMORY_ERROR);
  1777. }
  1778. secondderiv[0] = -0.5;
  1779. thistimestep = levtab[2] - levtab[0];
  1780. thisfrqstep = levtab[3] - levtab[1];
  1781. val1 = 3.0/thistimestep;
  1782. val2 = (thisfrqstep/thistimestep) - firstderivatzero;
  1783. u[0] = val1 * val2;
  1784. lasttime = levtab[0];
  1785. lastval = levtab[1];
  1786. for(n = 1,t = 2, v = 3, tt = 4, vv = 5; n < arraysize - 1;n++,t+=2,v+=2,tt+=2,vv +=2) { // t indexes current times in brktable, v indexes current values
  1787. thisfrqstep = levtab[v] - lastval; // tt indexes NEXT time, vv indexes NEXT value
  1788. nextfrqstep = levtab[vv] - levtab[v];
  1789. thistimestep = levtab[t] - lasttime;
  1790. nexttimestep = levtab[tt] - levtab[t];
  1791. bigtimestep = levtab[tt] - lasttime;
  1792. sig = thistimestep/bigtimestep;
  1793. p = (sig * secondderiv[n-1]) + 2.0;
  1794. secondderiv[n] = (sig - 1.0)/p;
  1795. u[n] = (nextfrqstep/nexttimestep) - (thisfrqstep/thistimestep);
  1796. u[n] = (6.0 * u[n])/bigtimestep;
  1797. u[n] -= sig * u[n-1];
  1798. u[n] /= p;
  1799. lasttime = levtab[t];
  1800. lastval = levtab[v];
  1801. }
  1802. qn = 0.5;
  1803. thisfrqstep = levtab[v] - lastval;
  1804. thistimestep = levtab[t] - lasttime;
  1805. val1 = 3.0/thistimestep;
  1806. val2 = firstderivatend - (thisfrqstep/thistimestep);
  1807. un = val1 * val2;
  1808. val1 = un - (qn * u[n-1]);
  1809. val2 = (qn * secondderiv[n-1]) + 1.0;
  1810. secondderiv[n] = val1/val2;
  1811. for(k = n-1;k >= 0;k--)
  1812. secondderiv[k] = (secondderiv[k] * secondderiv[k+1]) + u[k];
  1813. return FINISHED;
  1814. }
  1815. /*************************************** SPLINT *******************************
  1816. *
  1817. * Do cubic spline, using 2nd dervatives table.
  1818. */
  1819. double splint(int streamno,double time,int islevel,dataptr dz)
  1820. {
  1821. double *datatab, *secondderiv;
  1822. int arraysize = dz->datasize;
  1823. int hitim, lotim, hival, loval; // time and value indeces into brkpoint array
  1824. int hideriv, loderiv; // upper and lower indices into 2nd derivatives array
  1825. double timestep, hitimefrac, lotimefrac, val1, val2, val3;
  1826. if(islevel) {
  1827. datatab = dz->parray[dz->rotlevel+streamno];
  1828. secondderiv = dz->parray[dz->levderivs+streamno];
  1829. } else {
  1830. datatab = dz->parray[streamno];
  1831. secondderiv = dz->parray[dz->derivs+streamno];
  1832. }
  1833. if(time <= datatab[0])
  1834. return datatab[1];
  1835. hideriv = 0;
  1836. hitim = 0;
  1837. while(time > datatab[hitim]) {
  1838. hitim+=2;
  1839. hideriv++;
  1840. if(hideriv >= arraysize)
  1841. return datatab[(arraysize * 2)-1]; // last value in table
  1842. }
  1843. loderiv = hideriv - 1;
  1844. lotim = hitim - 2;
  1845. loval = lotim+1;
  1846. hival = hitim+1;
  1847. timestep = datatab[hitim] - datatab[lotim];
  1848. hitimefrac = (datatab[hitim] - time)/timestep;
  1849. lotimefrac = (time - datatab[lotim])/timestep;
  1850. val1 = hitimefrac * datatab[loval];
  1851. val1 += lotimefrac * datatab[hival];
  1852. val2 = (hitimefrac * hitimefrac * hitimefrac) - hitimefrac;
  1853. val2 *= secondderiv[loderiv];
  1854. val3 = (lotimefrac * lotimefrac * lotimefrac) - lotimefrac;
  1855. val3 *= secondderiv[hideriv];
  1856. val2 += val3;
  1857. val2 *= (timestep * timestep)/6.0;
  1858. val1 += val2;
  1859. return val1;
  1860. }
  1861. /****************************** STRANDS ***********************************/
  1862. int strands(double pitchrange,double band_separation,double tessitura,int isturb,dataptr dz)
  1863. {
  1864. int exit_status, n, t, flow_type, istwist = 0, *permlocal = NULL, *permglobal = NULL, rotup = dz->iparam[STRAND_3D], thth, threadscnt;
  1865. int outcnt = 0, entrycnt;
  1866. double time = 0.0;
  1867. double *lastcycendtime, *bandtwist, *tabpos, *bandtopmean, *bandtop, *bandbot, *phasoffset, *flow;
  1868. double *wtabpos, *wavyfrq, *lampitch, *turbpset = NULL, *localturbpitch = NULL, *globalturbpitch = NULL;
  1869. double bandhalfgap, frqrange, frqmin, speedscat, squeeze, bandwidth, halfbandwidth, bandcentre, lasttabpos, thistabpos, thistabpos2, sinval;
  1870. int *cycend, *wcycend, dummycycend, piover2phaseshift, piphaseshift, phasdist, th, bandno, threadbas, newcycle, iswavy, lastiswavy, *threadlens = NULL;
  1871. double lamstep, halflamstep, pitchwander, level, twistreffrq = 0.0, gturb;
  1872. double transittime = 0.0, transitfrac, laminarpitch, thisthreadcentre, thishalfbandwidth, thisturb;
  1873. double upbandwidth, dnbandwidth, upbandlim, dnbandlim, xs, lamlevel, pitch, transitstart, vamp, thisbandbot;
  1874. if(dz->mode == 2)
  1875. threadlens = dz->iparray[0]; // Time of end of previous twist-cycle
  1876. // Used when scattering stream-times within cycle
  1877. if((lastcycendtime = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1878. sprintf(errstr,"INSUFFICIENT MEMORY for storing endtime of cycle in each band.\n");
  1879. return(MEMORY_ERROR);
  1880. } // Flag that band's twist cycle has been completed
  1881. if((cycend = (int *)malloc(dz->iparam[STRAND_BANDS] * sizeof(int)))==NULL) {
  1882. sprintf(errstr,"INSUFFICIENT MEMORY for storing twist cycle completion flags.\n");
  1883. return(MEMORY_ERROR);
  1884. }
  1885. for(bandno = 0;bandno < dz->iparam[STRAND_BANDS];bandno++) { // Initialise all cycle-end flags to 0
  1886. lastcycendtime[bandno] = 0.0;
  1887. cycend[bandno] = 0;
  1888. } // frq of each laminar thread
  1889. if((lampitch = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1890. sprintf(errstr,"INSUFFICIENT MEMORY for storing frqs of laminar threads.\n");
  1891. return(MEMORY_ERROR);
  1892. } // twisting rate of each band
  1893. if((bandtwist = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1894. sprintf(errstr,"INSUFFICIENT MEMORY for storing twist rate of each band.\n");
  1895. return(MEMORY_ERROR);
  1896. } // Sintable read-position for each thread
  1897. if((tabpos = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1898. sprintf(errstr,"INSUFFICIENT MEMORY for storing sinetable read-position in each band.\n");
  1899. return(MEMORY_ERROR);
  1900. } // Sintable read-position for wavy band-boundaries
  1901. if((wtabpos = (double *)malloc((dz->iparam[STRAND_BANDS] - 1) * sizeof(double)))==NULL) {
  1902. sprintf(errstr,"INSUFFICIENT MEMORY for storing Sintable read-position for wavy band-boundaries.\n");
  1903. return(MEMORY_ERROR);
  1904. } // wavy band-boundaries oscillation-frequency
  1905. if((wcycend = (int*)malloc((dz->iparam[STRAND_BANDS] - 1) * sizeof(int)))==NULL) {
  1906. sprintf(errstr,"INSUFFICIENT MEMORY for storing Sintable cycle end markers for wavy band-boundaries.\n");
  1907. return(MEMORY_ERROR);
  1908. } // wavy band-boundaries oscillation-frequency
  1909. if((wavyfrq = (double *)malloc((dz->iparam[STRAND_BANDS] - 1) * sizeof(double)))==NULL) {
  1910. sprintf(errstr,"INSUFFICIENT MEMORY for storing wavy band-boundaries oscillation-frequency.\n");
  1911. return(MEMORY_ERROR);
  1912. } // upper boundary pitches of each band (ignoring any gapping)
  1913. if((bandtopmean = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1914. sprintf(errstr,"INSUFFICIENT MEMORY for storing upper boundary pitches of each band.\n");
  1915. return(MEMORY_ERROR);
  1916. } // lower boundary pitches of each band (ignoring any gapping)
  1917. if((bandtop = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1918. sprintf(errstr,"INSUFFICIENT MEMORY for storing lower boundary pitches of each band.\n");
  1919. return(MEMORY_ERROR);
  1920. } // Current bottom pitch of each band
  1921. if((bandbot = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
  1922. sprintf(errstr,"INSUFFICIENT MEMORY for storing Current bottom pitch of each band.\n");
  1923. return(MEMORY_ERROR);
  1924. } // Phase offset of pointers defining streams within a band
  1925. if((phasoffset = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1926. sprintf(errstr,"INSUFFICIENT MEMORY for storing Phase offset of pointers defining streams within a band.\n");
  1927. return(MEMORY_ERROR);
  1928. }
  1929. if(isturb) {
  1930. if((turbpset = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1931. sprintf(errstr,"INSUFFICIENT MEMORY for storing pre-assigned turbulence pitches.\n");
  1932. return(MEMORY_ERROR);
  1933. }
  1934. if((localturbpitch = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1935. sprintf(errstr,"INSUFFICIENT MEMORY for storing local turbulence pitches.\n");
  1936. return(MEMORY_ERROR);
  1937. }
  1938. if((globalturbpitch = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
  1939. sprintf(errstr,"INSUFFICIENT MEMORY for storing global turbulence pitches.\n");
  1940. return(MEMORY_ERROR);
  1941. }
  1942. if((permlocal = (int *)malloc(dz->itemcnt * sizeof(int)))==NULL) {
  1943. sprintf(errstr,"INSUFFICIENT MEMORY for storing local turbulence pitches.\n");
  1944. return(MEMORY_ERROR);
  1945. }
  1946. if((permglobal = (int *)malloc(dz->itemcnt * sizeof(int)))==NULL) {
  1947. sprintf(errstr,"INSUFFICIENT MEMORY for storing global turbulence pitches.\n");
  1948. return(MEMORY_ERROR);
  1949. }
  1950. for(n=0;n < dz->itemcnt;n++) {
  1951. permlocal[n] = n;
  1952. permglobal[n] = n;
  1953. }
  1954. }
  1955. flow = dz->parray[dz->flowdata];
  1956. // Establish phase-offset for 3-d motion : level mix is PI/2 out of phase with pitch-reading.
  1957. piover2phaseshift = (int)round((double)SYNTH_TABSIZE/4.0);
  1958. piphaseshift = (int)round((double)SYNTH_TABSIZE/2.0);
  1959. thth = 0;
  1960. if(dz->mode == 2) {
  1961. // Establish phase-offset of streams within bands
  1962. for(n = 0;n < dz->iparam[STRAND_BANDS];n++) {
  1963. threadscnt = threadlens[n];
  1964. phasdist = (int)round((double)SYNTH_TABSIZE/(double)threadscnt);
  1965. for(th = 0;th < threadscnt;th++) {
  1966. phasoffset[thth] = th * phasdist;
  1967. thth++;
  1968. }
  1969. }
  1970. } else {
  1971. // Establish phase-offset of streams within bands
  1972. phasdist = (int)round((double)SYNTH_TABSIZE/(double)dz->iparam[STRAND_THRDS]);
  1973. for(n = 0;n < dz->iparam[STRAND_BANDS];n++) {
  1974. for(th = 0;th < dz->iparam[STRAND_THRDS];th++) {
  1975. phasoffset[thth] = th * phasdist;
  1976. thth++;
  1977. }
  1978. }
  1979. }
  1980. // Preset phase-of sinetable read for threads in each band
  1981. for(th = 0;th < dz->itemcnt;th++)
  1982. tabpos[th] = phasoffset[th];
  1983. // Get initial value of all time-varying variables
  1984. time = 0;
  1985. if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
  1986. return exit_status;
  1987. // Intialise band boundaries (before any gapping)
  1988. bandhalfgap = dz->param[STRAND_GAP]/2.0;
  1989. bandtopmean[0] = dz->param[STRAND_BOT] + band_separation; // bandtopmean is generally in the gap between bands,
  1990. for(bandno=1; bandno < dz->iparam[STRAND_BANDS]-1;bandno++) // or at the top and bottom limits of entire pitchrange
  1991. bandtopmean[bandno] = bandtopmean[bandno-1] + band_separation;
  1992. bandtopmean[bandno] = dz->param[STRAND_TOP]; // bandtopmean is generally in the gap between bands,
  1993. // Initialise actual band limits (after gapping)
  1994. bandbot[0] = dz->param[STRAND_BOT];
  1995. for(bandno=1; bandno < dz->iparam[STRAND_BANDS];bandno++)
  1996. bandbot[bandno] = bandtopmean[bandno-1] + bandhalfgap;
  1997. for(bandno=0; bandno < dz->iparam[STRAND_BANDS] - 1;bandno++)
  1998. bandtop[bandno] = bandtopmean[bandno] - bandhalfgap;
  1999. bandtop[bandno] = dz->param[STRAND_TOP];
  2000. // Preset all wavyfrequences, for waviness of band boundaries
  2001. lastiswavy = 0;
  2002. // Initialise all frqs for any possible laminar flow
  2003. lamstep = pitchrange/(double)(dz->itemcnt - 1);
  2004. halflamstep = lamstep/2.0;
  2005. lampitch[0] = dz->param[STRAND_BOT];
  2006. for(th = 1;th < dz->itemcnt-1; th++)
  2007. lampitch[th] = lampitch[th-1] + lamstep;
  2008. lampitch[th] = dz->param[STRAND_TOP];
  2009. // Initialise all frqs for any possible twisted flow
  2010. for(n=0,t=0;n < dz->flowcnt;n++,t+=4) {
  2011. flow_type = (int)round(flow[t+1]);
  2012. if(flow_type != LAMINAR) { // TOTWIST,and FROMTWIST (as well as TWISTED) both need bandtwist-frq values etc
  2013. transitstart = flow[t];
  2014. twistreffrq = flow[t+2];
  2015. transittime = flow[t+3];
  2016. istwist = 1;
  2017. break;
  2018. }
  2019. }
  2020. if(istwist) {
  2021. for(bandno = 0;bandno < dz->iparam[STRAND_BANDS];bandno++) {
  2022. bandtwist[bandno] = twistreffrq; // get twist-freq of band read from start of true twist
  2023. if(dz->param[STRAND_RAND] > 0.0) { // If randomised (from one band to another): generate random scatter
  2024. speedscat = drand48() * dz->param[STRAND_RAND];
  2025. speedscat += 1.0; // Allowing frq-scatter in range *1 to (max)*2
  2026. if(drand48() < 0.5) // and, at random, select N or 1/N (maximal range *1/2 to *2)
  2027. speedscat = 1.0/speedscat;
  2028. bandtwist[bandno] *= speedscat; // and set randomised value as true twist-frequency of band
  2029. }
  2030. }
  2031. }
  2032. flow_type = get_flow_type(0.0,&transitstart,&twistreffrq,&transittime,dz);
  2033. while(outcnt < dz->datasize) {
  2034. if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
  2035. return exit_status;
  2036. iswavy = 0;
  2037. if(dz->param[STRAND_VAMP] > 0.0 && (dz->param[STRAND_VMIN] > 0.0 || dz->param[STRAND_VMAX] > 0.0))
  2038. iswavy = 1;
  2039. if(!lastiswavy && iswavy) { // When waviness starts, set up cycle reading in sintable
  2040. frqrange = fabs(dz->param[STRAND_VMAX] - dz->param[STRAND_VMIN]);
  2041. frqmin = min(dz->param[STRAND_VMAX],dz->param[STRAND_VMIN]);
  2042. for(bandno = 0; bandno < dz->iparam[STRAND_BANDS] - 1; bandno++) {
  2043. wavyfrq[bandno] = drand48() * frqrange;
  2044. wavyfrq[bandno] += frqmin;
  2045. wcycend[bandno] = 0;
  2046. }
  2047. }
  2048. lastiswavy = iswavy;
  2049. switch(flow_type) {
  2050. case(LAMINAR):
  2051. for(th = 0;th < dz->itemcnt;th++) {
  2052. pitch = lampitch[th];
  2053. pitchwander = dz->param[STRAND_RAND] * halflamstep;
  2054. if(th == 0)
  2055. pitchwander *= drand48();
  2056. else if(th == dz->itemcnt - 1)
  2057. pitchwander *= -drand48();
  2058. else
  2059. pitchwander *= (drand48() * 2.0) - 1.0;
  2060. pitch += pitchwander;
  2061. entrycnt = outcnt * 2; // Save pitch vals generated
  2062. dz->parray[th][entrycnt++] = time;
  2063. dz->parray[th][entrycnt++] = pitch;
  2064. if(dz->iparam[STRAND_3D]) {
  2065. level = dz->param[STRAND_SCAT] * drand48();
  2066. level = 1.0 - level;
  2067. entrycnt = outcnt * 2; // Save level vals generated
  2068. dz->parray[dz->rotlevel+th][entrycnt++] = time;
  2069. dz->parray[dz->rotlevel+th][entrycnt++] = level;
  2070. entrycnt = outcnt * 2; // Dummy values for reverb-etc mix
  2071. dz->parray[dz->rotmix+th][entrycnt++] = time;
  2072. dz->parray[dz->rotmix+th][entrycnt++] = 0.0;
  2073. }
  2074. }
  2075. break;
  2076. case(TWISTED):
  2077. rotup = dz->iparam[STRAND_3D];
  2078. // IF TURBULENCE IS (APPROACHING) GLOBAL: calculate turbulence pitches over entire range, across all bands
  2079. if(dz->param[STRAND_TURB] >= 1.0)
  2080. assign_turbulence_pitches(dz->itemcnt,dz->param[STRAND_BOT],pitchrange,permglobal,turbpset,globalturbpitch);
  2081. // for each band in turn
  2082. threadbas = 0;
  2083. for(bandno = 0;bandno < dz->iparam[STRAND_BANDS]; bandno++) {
  2084. if(dz->mode == 2)
  2085. threadscnt = threadlens[bandno];
  2086. else {
  2087. threadscnt = dz->iparam[STRAND_THRDS];
  2088. threadbas = bandno * dz->iparam[STRAND_THRDS]; // Get index of lowest thread in band
  2089. }
  2090. // IF TURBULENCE IS IN-BAND OR GLOBAL: Calculate turbulence pitches WITHIN band
  2091. if(dz->param[STRAND_TURB] > 0.0) {
  2092. if(bandno == 0)
  2093. thisbandbot = dz->param[STRAND_BOT];
  2094. else
  2095. thisbandbot = bandtopmean[bandno-1];
  2096. assign_turbulence_pitches(threadscnt,thisbandbot,tessitura,permlocal + threadbas,turbpset,localturbpitch);
  2097. }
  2098. // If at end of a twist cylce for the band, scatter previous cycle times, and recalculate twist frequency
  2099. newcycle = 0;
  2100. if(cycend[bandno]) { // If band twist-cycle reaches sintab end
  2101. if(dz->param[STRAND_SCAT] > 0.0) // Scatter data in this band, over last cycle
  2102. scatter_streamdata_in_last_cycle(time,bandno,threadscnt,threadbas,outcnt,lastcycendtime[bandno],dz);
  2103. lastcycendtime[bandno] = time; // Note start of next cycle
  2104. cycend[bandno] = 0; // Unmark "end of cycle"
  2105. newcycle = 1;
  2106. bandtwist[bandno] = dz->param[STRAND_TWIST]; // get twist-freq of band read from input data
  2107. if(dz->param[STRAND_RAND] > 0.0) { // If randomised (from one band to another): generate random scatter
  2108. speedscat = drand48() * dz->param[STRAND_RAND];
  2109. speedscat += 1.0; // Allowing frq-scatter in range *1 to (max)*2
  2110. if(drand48() < 0.5) // and, at random, select N or 1/N (maximal range *1/2 to *2)
  2111. speedscat = 1.0/speedscat;
  2112. bandtwist[bandno] *= speedscat; // and set randomised value as true twist-frequency of band
  2113. }
  2114. }
  2115. if(bandno < dz->iparam[STRAND_BANDS] - 1) {
  2116. // Use warp factors to get any wavy-variation of top boundary for current band (except for top of top band which is fixed)
  2117. if(iswavy && dz->param[STRAND_TURB] < 1.0) { // If Turbulence >= 1, no longer ness to calc wavy-boundaries
  2118. vamp = dz->param[STRAND_VAMP]; // Amplitude of waviness decreases as turbulence increases (0->1)
  2119. if(dz->param[STRAND_TURB] > 0.0) // The factor (1 - turbulence), with values (1->0) is used.
  2120. vamp *= pow((1 - dz->param[STRAND_TURB]),TURBFLATTEN); // TURBFLATTEN makes curve dip towards zero more quickly at start.
  2121. bandtop[bandno] = wavy(bandno,bandtopmean[bandno],tessitura,vamp,&(wavyfrq[bandno]),&(wtabpos[bandno]),&(wcycend[bandno]),dz->scaler,dz);
  2122. // Use halfgap to force band separation
  2123. bandtop[bandno] -= bandhalfgap;
  2124. } else
  2125. bandtop[bandno] = bandtopmean[bandno] - bandhalfgap;
  2126. } // Use previously calcd value of top of next lowest band,
  2127. if(bandno > 0) // to find bottom boundary of current band.
  2128. bandbot[bandno] = bandtop[bandno - 1] + dz->param[STRAND_GAP]; // using gap to force band separation
  2129. // Use band minimum width to modify values, if ness
  2130. bandwidth = bandtop[bandno] - bandbot[bandno];
  2131. if((squeeze = dz->param[STRAND_MINB] - bandwidth) > 0) {
  2132. bandtop[bandno] += squeeze;
  2133. bandwidth = bandtop[bandno] - bandbot[bandno];
  2134. }
  2135. halfbandwidth = bandwidth/2.0;
  2136. bandcentre = bandbot[bandno] + halfbandwidth;
  2137. // SAFETY: recalibrate the phase-offsets for the strans
  2138. if(newcycle) {
  2139. for(th=1;th<threadscnt;th++) {
  2140. tabpos[threadbas + th] = tabpos[threadbas] + phasoffset[threadbas + th];
  2141. if(tabpos[threadbas + th] >= SYNTH_TABSIZE)
  2142. tabpos[threadbas + th] -= (double)SYNTH_TABSIZE;
  2143. }
  2144. newcycle = 0;
  2145. }
  2146. thisturb = dz->param[STRAND_TURB];
  2147. for(th=0;th<threadscnt;th++) {
  2148. lasttabpos = tabpos[threadbas+th]; // Remember current table location
  2149. if(thisturb == 2.0) // TOTAL GLOBAL TURBULENCE
  2150. pitch = globalturbpitch[threadbas+th]; // use global turbulence pitch
  2151. else if(thisturb >= 1.0) // TOTAL INBAND TURBULENCE or beyond
  2152. pitch = localturbpitch[threadbas+th]; // use in-band turbulent pitch
  2153. else { // turb < 1.0 // ELSE: (some degree of) TWISTING : Read sintable at correct location
  2154. if(th==0) // ONLY lowest thread used to count cycles
  2155. sinval = sinread(1,&(tabpos[threadbas]),bandtwist[bandno],&(cycend[bandno]),dz->scaler,dz);
  2156. else
  2157. sinval = sinread(1,&(tabpos[threadbas+th]),bandtwist[bandno],&dummycycend,dz->scaler,dz);
  2158. pitch = sinval * halfbandwidth; // Expand -1-to +1 range to fit into bandwidth
  2159. pitch += bandcentre;
  2160. }
  2161. if(thisturb > 0.0) { // If turbulent
  2162. if(thisturb < 1.0) // MOVING TOWARDS INBAND TURBULENCE :
  2163. // pitch is from sinval : interpolate towards in-band turbulent pitch
  2164. pitch = ((1.0 - thisturb) * pitch) + (thisturb * localturbpitch[threadbas+th]);
  2165. else if(thisturb < 2.0) { // thisturb >= 1.0
  2166. gturb = thisturb - 1.0; // MOVING TOWARDS GLOBAL TURBULENCE :
  2167. // pitch is from localturbpitch : interpolate towards global turbulent pitch
  2168. pitch = ((1.0 - gturb) * pitch) + (gturb * globalturbpitch[threadbas+th]);
  2169. }
  2170. }
  2171. entrycnt = outcnt * 2; // Save pitch vals generated
  2172. dz->parray[threadbas + th][entrycnt++] = time;
  2173. dz->parray[threadbas + th][entrycnt++] = pitch;
  2174. if(rotup) { // If band is to turn in radial direction
  2175. switch(rotup) { // generate phase-shifted data for mixing filtered copy
  2176. case(1):
  2177. thistabpos = lasttabpos + piover2phaseshift; // Rotating UP at the front
  2178. while(thistabpos >= SYNTH_TABSIZE)
  2179. thistabpos -= (double)SYNTH_TABSIZE;
  2180. thistabpos2 = lasttabpos + piphaseshift;
  2181. while(thistabpos2 >= SYNTH_TABSIZE)
  2182. thistabpos2 -= (double)SYNTH_TABSIZE;
  2183. break;
  2184. case(-1): // Rotating DOWN at the front
  2185. thistabpos = lasttabpos - piover2phaseshift;
  2186. while(thistabpos < 0)
  2187. thistabpos += (double)SYNTH_TABSIZE;
  2188. thistabpos2 = lasttabpos;
  2189. break;
  2190. }
  2191. sinval = sinread(1,&thistabpos,bandtwist[bandno],&dummycycend,dz->scaler,dz);
  2192. level = sinval + 1.0; // Scale into 0 to 1 range
  2193. level /= 2.0;
  2194. if(dz->param[STRAND_TURB] > 0.0)
  2195. level = turblevel(dz->param[STRAND_TURB],level,dz);
  2196. entrycnt = outcnt * 2; // Save mixdata values
  2197. dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = time;
  2198. dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = level;
  2199. sinval = sinread(1,&thistabpos2,bandtwist[bandno],&dummycycend,dz->scaler,dz);
  2200. level = sinval + 1.0; // Scale into 0 to 1 range
  2201. level /= 2.0;
  2202. if(dz->param[STRAND_TURB] > 0.0) // THIS IS ILLOGICAL, BUT perhaps OK for turbulent flow!!
  2203. level = turblevel(dz->param[STRAND_TURB],level,dz);
  2204. entrycnt = outcnt * 2; // Save mixdata values
  2205. dz->parray[dz->rotmix + threadbas + th][entrycnt++] = time;
  2206. dz->parray[dz->rotmix + threadbas + th][entrycnt++] = level;
  2207. }
  2208. }
  2209. rotup = -rotup; // If rotating, alternate bands rotate in opposite directions
  2210. if(dz->mode == 2)
  2211. threadbas += threadscnt;
  2212. }
  2213. break;
  2214. case(TOTWIST):
  2215. case(FROMTWIST):
  2216. rotup = dz->iparam[STRAND_3D];
  2217. transitfrac = (time - transitstart)/transittime; // Fractional position in transit to full twisting
  2218. // THE FOLLOWING CODE IS DONE AS IF WE'RE ALREADY IN A FULL TWIST
  2219. threadbas = 0;
  2220. for(bandno = 0;bandno < dz->iparam[STRAND_BANDS]; bandno++) {
  2221. if(dz->mode == 2)
  2222. threadscnt = threadlens[bandno];
  2223. else {
  2224. threadscnt = dz->iparam[STRAND_THRDS];
  2225. threadbas = bandno * dz->iparam[STRAND_THRDS];
  2226. }
  2227. newcycle = 0;
  2228. if(cycend[bandno]) {
  2229. if(dz->param[STRAND_SCAT] > 0.0)
  2230. scatter_streamdata_in_last_cycle(time,bandno,threadscnt,threadbas,outcnt,lastcycendtime[bandno],dz);
  2231. lastcycendtime[bandno] = time;
  2232. cycend[bandno] = 0;
  2233. newcycle = 1;
  2234. bandtwist[bandno] = twistreffrq;
  2235. if(dz->param[STRAND_RAND] > 0.0) {
  2236. speedscat = drand48() * dz->param[STRAND_RAND];
  2237. speedscat += 1.0;
  2238. if(drand48() < 0.5)
  2239. speedscat = 1.0/speedscat;
  2240. bandtwist[bandno] *= speedscat;
  2241. }
  2242. }
  2243. // WAVY BAND BOUNDARIES NOT PERMITTED IN TRANSITION TO TWIST
  2244. if(bandno < dz->iparam[STRAND_BANDS] - 1)
  2245. bandtop[bandno] = bandtopmean[bandno] - bandhalfgap;
  2246. if(bandno > 0)
  2247. bandbot[bandno] = bandtop[bandno - 1] + bandhalfgap;
  2248. bandwidth = bandtop[bandno] - bandbot[bandno];
  2249. if((squeeze = dz->param[STRAND_MINB] - bandwidth) > 0) {
  2250. bandtop[bandno] += squeeze;
  2251. bandwidth = bandtop[bandno] - bandbot[bandno];
  2252. }
  2253. halfbandwidth = bandwidth/2.0;
  2254. bandcentre = bandbot[bandno] + halfbandwidth;
  2255. if(newcycle) {
  2256. for(th=1;th<threadscnt;th++) {
  2257. tabpos[threadbas + th] = tabpos[threadbas] + phasoffset[threadbas + th];
  2258. if(tabpos[threadbas + th] >= SYNTH_TABSIZE)
  2259. tabpos[threadbas + th] -= (double)SYNTH_TABSIZE;
  2260. }
  2261. }
  2262. // WE NOW INTEGRATE THE LAMINAR AND THE TWIST INFORMATION
  2263. if(flow_type == TOTWIST)
  2264. bandwidth *= transitfrac; // Twist bandwidth increases from zero to full as we do transit to twist
  2265. else
  2266. bandwidth *= (1.0 - transitfrac); // Twist bandwidth decreases from full to zero as we do transit from twist
  2267. // CALCUALTE POSITION IF IT WERE LAMINAR
  2268. for(th=0;th<threadscnt;th++) {
  2269. laminarpitch = lampitch[th+threadbas];
  2270. pitchwander = dz->param[STRAND_RAND] * halflamstep;
  2271. if(th+threadbas == 0)
  2272. pitchwander *= drand48();
  2273. else if(th+threadbas == dz->itemcnt - 1)
  2274. pitchwander *= -drand48();
  2275. else
  2276. pitchwander *= (drand48() * 2.0) - 1.0;
  2277. laminarpitch += pitchwander;
  2278. // INTERPOLATE btween laminar position and band-centre of twisting-threads
  2279. if(flow_type == TOTWIST) { // as we approach true twist
  2280. thisthreadcentre = (bandcentre - laminarpitch) * transitfrac;
  2281. thisthreadcentre += laminarpitch;
  2282. } else { // as we approach laminar
  2283. thisthreadcentre = (laminarpitch - bandcentre) * transitfrac;
  2284. thisthreadcentre += bandcentre;
  2285. }
  2286. // Find upper/lower limits of stream rotating around current centre (at it expands/contracts to/from full bandwidth)
  2287. thishalfbandwidth = bandwidth/2.0;
  2288. upbandwidth = thishalfbandwidth;
  2289. dnbandwidth = thishalfbandwidth;
  2290. upbandlim = thisthreadcentre + thishalfbandwidth;
  2291. dnbandlim = thisthreadcentre - thishalfbandwidth;
  2292. // Check total limits of band range are not exceeded
  2293. if((xs = upbandlim - bandtop[bandno]) > 0) {
  2294. upbandwidth -= xs;
  2295. dnbandwidth += xs;
  2296. } else if((xs = bandbot[bandno] - dnbandlim) > 0) {
  2297. dnbandwidth -= xs;
  2298. upbandwidth += xs;
  2299. }
  2300. // CALCULATE POSITION IN A TWIST
  2301. lasttabpos = tabpos[threadbas+th];
  2302. if(th==0)
  2303. sinval = sinread(1,&(tabpos[threadbas]),bandtwist[bandno],&(cycend[bandno]),dz->scaler,dz);
  2304. else
  2305. sinval = sinread(1,&(tabpos[threadbas+th]),bandtwist[bandno],&dummycycend,dz->scaler,dz);
  2306. // SCALE TWIST POSITION INTO THE (narrowed) RANGE AROUND THE (moving) CENTRE
  2307. if(sinval >= 0.0) {
  2308. pitch = sinval * upbandwidth; // Expand -1-to +1 range to fit into current halfbandwidth
  2309. pitch += thisthreadcentre;
  2310. } else {
  2311. pitch = sinval * dnbandwidth; // NB sinval is initially -ve,
  2312. pitch += thisthreadcentre; // so adding it to bandcentre, takes it below bandcentre
  2313. }
  2314. entrycnt = outcnt * 2;
  2315. dz->parray[threadbas + th][entrycnt++] = time;
  2316. dz->parray[threadbas + th][entrycnt++] = pitch;
  2317. if(rotup) {
  2318. // calculate level for laminar flow
  2319. lamlevel = dz->param[STRAND_SCAT] * drand48();
  2320. lamlevel = 1.0 - lamlevel;
  2321. // calculate level for twisted flow
  2322. switch(rotup) {
  2323. case(1):
  2324. thistabpos = lasttabpos + piover2phaseshift; // Rotating UP at the front
  2325. while(thistabpos >= SYNTH_TABSIZE)
  2326. thistabpos -= (double)SYNTH_TABSIZE;
  2327. thistabpos2 = lasttabpos + piphaseshift;
  2328. while(thistabpos2 >= SYNTH_TABSIZE)
  2329. thistabpos2 -= (double)SYNTH_TABSIZE;
  2330. break;
  2331. case(-1): // Rotating DOWN at the front
  2332. thistabpos = lasttabpos - piover2phaseshift;
  2333. while(thistabpos < 0)
  2334. thistabpos += (double)SYNTH_TABSIZE;
  2335. thistabpos2 = lasttabpos;
  2336. break;
  2337. }
  2338. sinval = sinread(1,&thistabpos,bandtwist[bandno],&dummycycend,dz->scaler,dz);
  2339. level = sinval + 1.0;
  2340. level /= 2.0;
  2341. // Interpolate the two levels, according to
  2342. if(flow_type == TOTWIST) // how far we are into transit to full twist
  2343. level = (level * transitfrac) + (lamlevel * (1.0 - transitfrac));
  2344. else // how far we are into transit to full laminar
  2345. level = (level * (1.0 - transitfrac)) + (lamlevel * transitfrac);
  2346. entrycnt = outcnt * 2; // Save mixdata values
  2347. dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = time;
  2348. dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = level;
  2349. sinval = sinread(1,&thistabpos2,bandtwist[bandno],&dummycycend,dz->scaler,dz);
  2350. level = sinval + 1.0;
  2351. level /= 2.0;
  2352. // Interpolate the two mixlevels, according to
  2353. if(flow_type == TOTWIST) // how far we are into transit to full twist
  2354. level = level * transitfrac;
  2355. else // how far we are into transit to full laminar
  2356. level = level * (1.0 - transitfrac);
  2357. entrycnt = outcnt * 2; // Save mixdata values
  2358. dz->parray[dz->rotmix + threadbas + th][entrycnt++] = time;
  2359. dz->parray[dz->rotmix + threadbas + th][entrycnt++] = level;
  2360. }
  2361. }
  2362. rotup = -rotup;
  2363. if(dz->mode == 2)
  2364. threadbas += threadscnt;
  2365. }
  2366. break;
  2367. }
  2368. outcnt++;
  2369. time = outcnt * dz->param[STRAND_TSTEP];
  2370. flow_type = get_flow_type(time,&transitstart,&twistreffrq,&transittime,dz);
  2371. }
  2372. return FINISHED;
  2373. }
  2374. /****************************** OUTPUT_STRANDS ***********************************/
  2375. int output_strands(char *sfnam,dataptr dz)
  2376. {
  2377. int exit_status, n, m, j, k;
  2378. char temp[400];
  2379. double *stream;
  2380. dz->tempsize = dz->itemcnt;
  2381. // 1st data file already open
  2382. fprintf(stdout,"INFO: Outputting pitch-threads 1 to %d.\n",dz->itemcnt);
  2383. fflush(stdout);
  2384. for(n=0;n < dz->itemcnt;n++) {
  2385. if(sloom) { // Send valid message to progress-bar
  2386. dz->process_type = SCREEN_MESSAGE;
  2387. dz->process = FIND_PANPOS;
  2388. display_virtual_time(n+1,dz);
  2389. dz->process_type = TO_TEXTFILE;
  2390. dz->process = STRANDS;
  2391. }
  2392. if(n > 0) { // Current datafile closed as next is opened
  2393. if((exit_status = create_next_outfile(n,sfnam,temp,dz))<0)
  2394. return exit_status;
  2395. }
  2396. stream = dz->parray[n];
  2397. for(m = 0, j= 0; m < dz->datasize; m++,j+=2) {
  2398. sprintf(temp,"%.16lf\t%lf\n",stream[j],stream[j+1]);
  2399. if(fputs(temp,dz->fp) < 0) {
  2400. fclose(dz->fp);
  2401. sprintf(errstr,"CANNOT WRITE PITCH DATA TO FILE %s\n",dz->outfilename);
  2402. return SYSTEM_ERROR;
  2403. }
  2404. }
  2405. }
  2406. if(dz->iparam[STRAND_3D]) {
  2407. fprintf(stdout,"INFO: Outputting 1st set of control threads %d to %d.\n",dz->itemcnt + 1,dz->itemcnt * 2);
  2408. fflush(stdout);
  2409. for(k = 0,n=dz->itemcnt;k < dz->itemcnt;n++,k++) {
  2410. if(sloom) { // Send valid message to progress-bar
  2411. dz->process_type = SCREEN_MESSAGE;
  2412. dz->process = FIND_PANPOS;
  2413. display_virtual_time(k+1,dz);
  2414. dz->process_type = TO_TEXTFILE;
  2415. dz->process = STRANDS;
  2416. }
  2417. if((exit_status = create_next_outfile(n,sfnam,temp,dz))<0)
  2418. return exit_status;
  2419. stream = dz->parray[dz->rotlevel + k];
  2420. for(m = 0, j= 0; m < dz->datasize; m++,j+=2) {
  2421. sprintf(temp,"%.16lf\t%lf\n",stream[j],stream[j+1]);
  2422. if(fputs(temp,dz->fp) < 0) {
  2423. fclose(dz->fp);
  2424. sprintf(errstr,"CANNOT WRITE ROTATION-CONTROL1 DATA TO FILE %s\n",dz->outfilename);
  2425. return SYSTEM_ERROR;
  2426. }
  2427. }
  2428. }
  2429. fprintf(stdout,"INFO: Outputting 2nd set of control threads %d to %d.\n",(dz->itemcnt*2) + 1,dz->itemcnt * 3);
  2430. fflush(stdout);
  2431. for(k = 0,n=dz->itemcnt*2;k < dz->itemcnt;n++,k++) {
  2432. if(sloom) { // Send valid message to progress-bar
  2433. dz->process_type = SCREEN_MESSAGE;
  2434. dz->process = FIND_PANPOS;
  2435. display_virtual_time(k+1,dz);
  2436. dz->process_type = TO_TEXTFILE;
  2437. dz->process = STRANDS;
  2438. }
  2439. if((exit_status = create_next_outfile(n,sfnam,temp,dz))<0)
  2440. return exit_status;
  2441. stream = dz->parray[dz->rotmix + k];
  2442. for(m = 0, j= 0; m < dz->datasize; m++,j+=2) {
  2443. sprintf(temp,"%.16lf\t%lf\n",stream[j],stream[j+1]);
  2444. if(fputs(temp,dz->fp) < 0) {
  2445. fclose(dz->fp);
  2446. sprintf(errstr,"CANNOT WRITE ROTATION-CONTROL2 DATA TO FILE %s\n",dz->outfilename);
  2447. return SYSTEM_ERROR;
  2448. }
  2449. }
  2450. }
  2451. } // Last datafile is closed on "complete_output"
  2452. return FINISHED;
  2453. }
  2454. /**************************** CREATE_NEXT_OUTFILE ****************************/
  2455. int create_next_outfile(int no, char *sfnam, char *temp,dataptr dz)
  2456. {
  2457. int exit_status;
  2458. if(fclose(dz->fp) < 0) {
  2459. sprintf(errstr, "Failed to close file %s\n",dz->outfilename);
  2460. dz->process_type = OTHER_PROCESS; // prevents complaint at "complete output"
  2461. return(GOAL_FAILED);
  2462. }
  2463. strcpy(dz->outfilename,sfnam);
  2464. sprintf(temp,"%d",no);
  2465. strcat(dz->outfilename,temp);
  2466. if(!sloom)
  2467. strcat(dz->outfilename,".txt");
  2468. if((exit_status = create_sized_outfile(dz->outfilename,dz))<0) {
  2469. sprintf(errstr, "Failed to open file %s\n",dz->outfilename);
  2470. /*free(outfilename);*/
  2471. dz->process_type = OTHER_PROCESS; // prevents complaint at "complete output"
  2472. return(GOAL_FAILED);
  2473. }
  2474. return(FINISHED);
  2475. }
  2476. /**************************** SCATTER_STREAMDATA_IN_LAST_CYCLE ****************************/
  2477. void scatter_streamdata_in_last_cycle(double time,int bandno,int threadscnt,int threadbas, int outcnt,double lastcycendtime,dataptr dz)
  2478. {
  2479. double warp, cyclen, timefrac;
  2480. int n, m, k, t;
  2481. double *thisthread;
  2482. cyclen = time - lastcycendtime;
  2483. for(n=0,m= threadbas;n < threadscnt;n++,m++) { // For each stream in the band
  2484. thisthread = dz->parray[m]; // Get timewarp-value
  2485. warp = (dz->param[STRAND_SCAT] * (STRAND_MAXWARP - 1.0)); // Range of warping, some fraction of 1-to-maxwarp range
  2486. warp *= drand48(); // Get random value in range
  2487. warp += 1.0; // Add back the 1, so warp in range 1 to maxwarp
  2488. if(drand48() < 0.5)
  2489. warp = 1.0/warp; // Warp then randomly gets value warp or 1/warp
  2490. for(k=0,t=0;k < outcnt;k++,t+=2) { // Search the existing stored values
  2491. if(thisthread[t] > lastcycendtime) { // For any stored value within last cycle
  2492. timefrac = (thisthread[t] - lastcycendtime)/cyclen; // Find its time-position as a fraction of length of cycle (range 0-1)
  2493. timefrac = pow(timefrac,warp); // Warp its time-position (also range 0-1)
  2494. thisthread[t] = (cyclen * timefrac) + lastcycendtime; // Overwrite original timing
  2495. }
  2496. }
  2497. }
  2498. }
  2499. /**************************** WAVY ****************************
  2500. *
  2501. * Motion of boundaries between bands.
  2502. */
  2503. double wavy(int bandno,double bandtop_mean,double tessitura,double amp,double *wavyfrq,double *tabpos,int *cycend,double scaling,dataptr dz)
  2504. {
  2505. double range, sinval, frqrange, frqmin, bandtop;
  2506. sinval = sinread(0,tabpos,*wavyfrq,cycend,scaling,dz); // The tabpos is updated, the wavyfrq is fixed, the cycend is read
  2507. range = (tessitura * WAVYFRAC) * amp;
  2508. bandtop = bandtop_mean + (range * sinval);
  2509. if(*cycend) { // The wavyfrq is updated only at a cycle end
  2510. frqrange = fabs(dz->param[STRAND_VMAX] - dz->param[STRAND_VMIN]);
  2511. frqmin = min(dz->param[STRAND_VMAX],dz->param[STRAND_VMIN]);
  2512. *wavyfrq = drand48() * frqrange;
  2513. *wavyfrq += frqmin;
  2514. }
  2515. return bandtop;
  2516. }
  2517. /************************************** CHECK_TWIST_VARIABLE ****************************
  2518. *
  2519. * Twist can be zero at start of file,
  2520. * or be zero over a stretch of the file,
  2521. * i.e. there can be 2 adjacent zero values, but no more or less than 2, at any one location in the file.
  2522. */
  2523. int establish_flow_types(dataptr dz)
  2524. {
  2525. int n, m, twisttime, twistval, t, v, k, f, d, lastflowtype, flowtype;
  2526. int arraysize = dz->brksize[STRAND_TWIST];
  2527. double *flow, lasttime;
  2528. if(arraysize < 3)
  2529. dz->flowcnt = 1;
  2530. else {
  2531. for(n=2,m= 5;n < arraysize;n++,m+=2) {
  2532. if(twist[m] == 0.0 && twist[m-2] == 0.0 && twist[m-4] == 0.0) { // Compact any series of 3 zeros
  2533. for(k = n*2; k < arraysize*2;k++) // So zeros only exist, at most, in pairs
  2534. twist[k-2] = twist[k];
  2535. arraysize--;
  2536. n--;
  2537. m-=2;
  2538. }
  2539. }
  2540. dz->brksize[STRAND_TWIST] = arraysize;
  2541. lastflowtype = -1;
  2542. for(n=1,m= 3;n < arraysize;n++,m+=2) {
  2543. if(twist[m] == 0.0 && twist[m-2] == 0.0)
  2544. flowtype = LAMINAR;
  2545. else if(twist[m-2] == 0.0 && twist[m] != 0.0)
  2546. flowtype = TOTWIST;
  2547. else if(twist[m-2] != 0.0 && twist[m] == 0.0)
  2548. flowtype = FROMTWIST;
  2549. else
  2550. flowtype = TWISTED;
  2551. if(flowtype != lastflowtype) {
  2552. dz->flowcnt++;
  2553. lastflowtype = flowtype;
  2554. }
  2555. }
  2556. }
  2557. if((dz->parray[dz->flowdata] = (double *)malloc((dz->flowcnt * 4) * sizeof(double)))==NULL) {
  2558. sprintf(errstr,"INSUFFICIENT MEMORY for storing flow-types information.\n");
  2559. return(MEMORY_ERROR);
  2560. }
  2561. flow = dz->parray[dz->flowdata];
  2562. switch(arraysize) {
  2563. case(0):
  2564. flow[0] = 0.0;
  2565. if(dz->param[STRAND_TWIST] == 0) flow[1] = LAMINAR;
  2566. else flow[1] = TWISTED;
  2567. flow[2] = dz->param[STRAND_TWIST];
  2568. flow[3] = dz->param[STRAND_DUR];
  2569. break;
  2570. case(1):
  2571. flow[0] = 0.0;
  2572. if(dz->brk[STRAND_TWIST][1] == 0) flow[1] = LAMINAR;
  2573. else flow[1] = TWISTED;
  2574. flow[2] = dz->param[STRAND_TWIST];
  2575. flow[3] = dz->param[STRAND_DUR];
  2576. break;
  2577. default:
  2578. t = 0;
  2579. v = 1;
  2580. f = 2;
  2581. d = 3;
  2582. lastflowtype = -1;
  2583. lasttime = 0.0;
  2584. for(n=1,twisttime = 2,twistval = 3;n < arraysize;n++,twisttime+=2,twistval+=2) {
  2585. if(twist[twistval-2] == 0.0 && twist[twistval] == 0.0)
  2586. flowtype = LAMINAR;
  2587. else if(twist[twistval-2] == 0.0 && twist[twistval] != 0.0)
  2588. flowtype = TOTWIST;
  2589. else if(twist[twistval-2] != 0.0 && twist[twistval] == 0.0)
  2590. flowtype = FROMTWIST;
  2591. else
  2592. flowtype = TWISTED;
  2593. if(flowtype != lastflowtype) {
  2594. flow[t] = twist[twisttime-2]; // Time of start of new flow-type
  2595. flow[v] = flowtype; // Flow type
  2596. flow[d] = twist[twisttime] - lasttime; // Duration of totwist or fromtwist transition (if relevant)
  2597. lasttime = twist[twisttime];
  2598. switch(flowtype) {
  2599. case(TOTWIST):
  2600. flow[f] = twist[twistval]; // Twist value at true twist start (at end of transit)
  2601. break;
  2602. case(FROMTWIST):
  2603. case(TWISTED):
  2604. flow[f] = twist[twistval-2]; // Twist value at start of transit (end of previous true-twist)
  2605. break; // or start of true-twist (only used where flow starts with twist at time zero)
  2606. case(LAMINAR):
  2607. flow[f] = 0; // Value not used
  2608. break;
  2609. }
  2610. t+=4;
  2611. v+=4;
  2612. f+=4;
  2613. d+=4;
  2614. lastflowtype = flowtype;
  2615. }
  2616. }
  2617. flow[0] = 0.0; // Force start at zero time
  2618. break;
  2619. }
  2620. return FINISHED;
  2621. }
  2622. /******************************************* GET_FLOW_TYPE *********************************
  2623. *
  2624. * Read off the type of flow being generated, from prestored table.
  2625. */
  2626. int get_flow_type(double time,double *transitstart,double *twistreffrq,double *transittime,dataptr dz)
  2627. {
  2628. double *flow = dz->parray[dz->flowdata];
  2629. int n = 0, t = 0, flow_type;
  2630. while(time >= flow[t]) {
  2631. if(++n > dz->flowcnt) {
  2632. n--;
  2633. break;
  2634. }
  2635. t += 4;
  2636. }
  2637. t -= 4;
  2638. *transitstart = flow[t];
  2639. flow_type = (int)round(flow[t+1]);
  2640. *twistreffrq = flow[t+2];
  2641. *transittime = flow[t+3];
  2642. return flow_type;
  2643. }
  2644. /******************************************* TURBLEVEL *********************************/
  2645. double turblevel(double turbulence,double thislevel,dataptr dz)
  2646. {
  2647. double level;
  2648. level = drand48();
  2649. level = pow(level,TURBPOW);
  2650. if(turbulence < 1.0)
  2651. level = (level * turbulence) + (thislevel * (1.0 - turbulence));
  2652. return level;
  2653. }
  2654. /******************************************* CHECK_TURBULENCE_VALUES *********************************
  2655. *
  2656. * Flow can be turbulent (turbulence > 0.0) where flow is TWISTED.
  2657. */
  2658. int check_turbulence_values(int *isturb,dataptr dz)
  2659. {
  2660. int exit_status, flow_type, n, ft, starttime, endtime, turbcnt, tt, vv;
  2661. double *turb, *flow = dz->parray[dz->flowdata];
  2662. double turbmax, turbtime, turbval, flowstart, flowend;
  2663. // IF turbulence is fixed, and not zero
  2664. if(!dz->brksize[STRAND_TURB]) {
  2665. if(dz->param[STRAND_TURB] > 0.0) {
  2666. *isturb = 1;
  2667. // Turbulence everywhere: flow must be twisted everywhere
  2668. for(n=0,ft = 1; n < dz->flowcnt;n++,ft+=4) {
  2669. flow_type = (int)round(flow[ft]);
  2670. if(flow_type != TWISTED) {
  2671. sprintf(errstr,"Turbulence cannot exceed zero if flow is not twisted.\n");
  2672. return DATA_ERROR;
  2673. }
  2674. }
  2675. }
  2676. } else {
  2677. turb = dz->brk[STRAND_TURB];
  2678. if((exit_status = get_maxvalue_in_brktable(&turbmax,STRAND_TURB,dz))<0)
  2679. return exit_status;
  2680. if(turbmax > 0.0)
  2681. *isturb = 1;
  2682. if(dz->flowcnt == 1) {
  2683. // If only a single flow-type, this must be twisted if flow is ANYWHERE turbulent
  2684. flow_type = (int)round(flow[1]);
  2685. if(flow_type != TWISTED && turbmax > 0.0) {
  2686. sprintf(errstr,"Turbulence cannot exceed zero if flow is not twisted.\n");
  2687. return DATA_ERROR;
  2688. }
  2689. } else {
  2690. // Turbulence at specific times: must coincide with twisted flow
  2691. turbcnt = 0;
  2692. tt = 0;
  2693. vv = 1;
  2694. turbtime = turb[tt];
  2695. turbval = turb[vv];
  2696. for(n=0,starttime = 0,ft = 1,endtime = 3; n < dz->flowcnt-1;n++,starttime+=4,ft+=4,endtime +=4) {
  2697. flow_type = (int)round(flow[ft]);
  2698. // Check turbulence value in all NON-twisted flows
  2699. if(flow_type != TWISTED) {
  2700. flowstart = flow[starttime];
  2701. flowend = flow[endtime];
  2702. while(turbtime < flowstart) { // Advance in turbulence values into next flowtype
  2703. if(++turbcnt >= dz->brksize[STRAND_TURB])
  2704. break;
  2705. tt += 2;
  2706. vv += 2;
  2707. turbtime = turb[tt];
  2708. turbval = turb[vv];
  2709. }
  2710. if(turbtime < flowstart) { // If reached end of turbulence values,
  2711. if(turbval > 0.0) { // test last turbulence value against all further flows
  2712. if(++n < dz->flowcnt) { // (if there are any)
  2713. starttime += 4;
  2714. ft += 4;
  2715. for(;n <dz->flowcnt;n++,starttime+=4,ft+=4) {
  2716. flow_type = (int)round(flow[ft]);
  2717. if(flow_type != TWISTED) {
  2718. sprintf(errstr,"Turbulence at %c in non-twisted flow.\n",starttime);
  2719. return DATA_ERROR;
  2720. }
  2721. }
  2722. }
  2723. } // Then break out of outer test loop
  2724. break;
  2725. }
  2726. // ELSE turbtime >= flowstart :
  2727. // Test turbulence values within the NON-twisted flow
  2728. if(turbval > 0.0) {
  2729. sprintf(errstr,"Turbulence at %lf in non-twisted flow.\n",turbtime);
  2730. return DATA_ERROR;
  2731. }
  2732. while(turbtime < flowend) {
  2733. if(++turbcnt >= dz->brksize[STRAND_TURB])
  2734. break;
  2735. tt += 2;
  2736. vv += 2;
  2737. turbtime = turb[tt];
  2738. turbval = turb[vv];
  2739. if(turbval > 0.0) {
  2740. sprintf(errstr,"Turbulence at %lf in non-twisted flow.\n",turbtime);
  2741. return DATA_ERROR;
  2742. }
  2743. }
  2744. if(turbtime < flowend) { // Reached end of turbulence values,
  2745. if(turbval > 0.0) { // so test last turbulence value against all further flows
  2746. if(++n < dz->flowcnt) { // (if there are any)
  2747. starttime += 4;
  2748. ft += 4;
  2749. for(;n <dz->flowcnt;n++,starttime+=4,ft+=4) {
  2750. flow_type = (int)round(flow[ft]);
  2751. if(flow_type != TWISTED) {
  2752. sprintf(errstr,"Turbulence at %d in non-twisted flow.\n",starttime);
  2753. return DATA_ERROR;
  2754. }
  2755. }
  2756. }
  2757. } // Then break out of outer test loop
  2758. break;
  2759. }
  2760. }
  2761. }
  2762. }
  2763. }
  2764. return FINISHED;
  2765. }
  2766. /********************************************** TURBULENT_BANDSWAP ********************************
  2767. *
  2768. * Idea here is to invert the order of threads in some pattern to force bands to cross.
  2769. *
  2770. * *perm points to the lowest band (&perm[threadbas]) in the current band.
  2771. * e.g. with 4 streans per band, pointing to band 1, it points to the group perm[4][5][6][7]
  2772. * which initially have the values 4,5,6,7
  2773. * The process then permutes the values of this group.
  2774. * However these are permd, this set of perm VALUES (4567) will always lie in this locations perm[4-7]
  2775. *
  2776. * Threads are grouped into sets of "grpcnt".
  2777. * This grouping is selected AT RANDOM on each call.
  2778. * Then the order in each of these group is inverted.
  2779. *
  2780. * There are 5 possibilities
  2781. *
  2782. * (1) grpcnt = streamcnt
  2783. *
  2784. * e.g. streamcnt = 8 A B C D E F G H
  2785. * grpcnt = 8
  2786. * Reverse the entire set
  2787. * H G F E D C B A
  2788. *
  2789. * (2) grpcnt > 2 * streamcnt
  2790. *
  2791. * e.g. streamcnt = 8 A B C D E F G H
  2792. * grpcnt = 5
  2793. * Reverse lowest group first, then next lowest etc
  2794. * (there will be some double reversings)
  2795. * E D C B A f g h
  2796. * e d c H G F A B
  2797. *
  2798. *
  2799. * (3) grpcnt <= 2 * streamcnt, but divides streamcnt exactly
  2800. *
  2801. * e.g. streamcnt = 8 A B C D E F G H
  2802. * grpcnt = 2
  2803. * Reverse each group in turn
  2804. * B A c d e f g h
  2805. * b a D C e f g h
  2806. * b a d c F E g h
  2807. * b a d c f e G H
  2808. *
  2809. * (4) grpcnt <= 2 * streamcnt, but does NOT divide streamcnt exactly
  2810. * And remainder is 1
  2811. *
  2812. * e.g. streamcnt = 7 A B C D E F G
  2813. * grpcnt = 3
  2814. * Reverse each complete group
  2815. * C B A d e f g
  2816. * c b a F E D g
  2817. * Then rotate the whole set
  2818. * G c b a f e d
  2819. * OR
  2820. * (5) grpcnt <= 2 * streamcnt, but does NOT divide streamcnt exactly
  2821. * And remainder is > 1
  2822. *
  2823. * e.g. streamcnt = 8 a b c d e f g h
  2824. * grpcnt = 3
  2825. * Reverse each complete group, then the incomplete group
  2826. * grpcnt = 3 C B A d e f g h
  2827. * c b a F E D g h
  2828. * c b a f e d H G
  2829. *
  2830. */
  2831. void turbulent_bandswap(int *perm,int streamcnt)
  2832. {
  2833. int temp, n, m, k, setcnt, remainder;
  2834. int gpcnt = streamcnt - 1; // e.g. with 6 streams: no of groupings = 5 (2,3,4,5,6)
  2835. gpcnt = (int)floor(drand48() * gpcnt); // gpcnt range = 0 - 4
  2836. gpcnt += 2; // gpcnt range = 2 - 6
  2837. gpcnt = min(gpcnt,streamcnt); // Deal with vanishingly small probability that drand48() returns 1.0 exactly giving value 7!!
  2838. if(gpcnt == streamcnt) { // CASE 1
  2839. n = 0;
  2840. m = streamcnt - 1;
  2841. while(n < m) { // Invert entire group
  2842. temp = perm[n];
  2843. perm[n] = perm[m];
  2844. perm[m] = temp;
  2845. n++;
  2846. m--;
  2847. }
  2848. } else if(gpcnt > streamcnt * 2) { // CASE 2
  2849. n = 0;
  2850. m = gpcnt - 1;
  2851. while(n < m) { // Invert bottom-abutted group
  2852. temp = perm[n];
  2853. perm[n] = perm[m];
  2854. perm[m] = temp;
  2855. n++;
  2856. m--;
  2857. }
  2858. n = streamcnt - gpcnt;
  2859. m = streamcnt - 1;
  2860. while(n < m) { // Invert top-abutted group
  2861. temp = perm[n];
  2862. perm[n] = perm[m];
  2863. perm[m] = temp;
  2864. n++;
  2865. m--;
  2866. }
  2867. }
  2868. else {
  2869. setcnt = streamcnt/gpcnt;
  2870. for(k=0;k<setcnt;k++) {
  2871. n = k * gpcnt;
  2872. m = n + gpcnt - 1;
  2873. while(n < m) { // Invert each group in turn
  2874. temp = perm[n];
  2875. perm[n] = perm[m];
  2876. perm[m] = temp;
  2877. n++;
  2878. m--;
  2879. }
  2880. }
  2881. remainder = streamcnt%gpcnt;
  2882. switch(remainder) {
  2883. case(0): // CASE 3
  2884. break;
  2885. case(1): // CASE 4
  2886. temp = perm[streamcnt - 1];
  2887. n = streamcnt - 1;
  2888. while(n > 0) { // upshufl
  2889. perm[n] = perm[n-1];
  2890. n--;
  2891. } // take top to bottom
  2892. perm[0] = temp;
  2893. break;
  2894. default: // CASE 5
  2895. n = setcnt * gpcnt;
  2896. m = streamcnt - 1;
  2897. while(n < m) { // Invert the remnant set
  2898. temp = perm[n];
  2899. perm[n] = perm[m];
  2900. perm[m] = temp;
  2901. n++;
  2902. m--;
  2903. }
  2904. break;
  2905. }
  2906. }
  2907. }
  2908. /********************************************* ASSIGN_TURBULENCE_PITCHES ********************************************
  2909. *
  2910. * streamcnt = no of streams in band (or total number of streams)
  2911. * pitchbot = lowpitch boundary of band (or of entire range)
  2912. * pitchrange = pitchwidth of band (or of entire flow)
  2913. * perm = section of the perm array beginning at the lowest thread in this band
  2914. * (or entire perm array for all threads)
  2915. */
  2916. void assign_turbulence_pitches(int streamcnt,double pitchbot,double pitchrange,int *perm,double *turbpset,double *turbpitch)
  2917. {
  2918. int gotit = 0, n, m;
  2919. double maxrand = 0.0, minrand = 0.0, randrange, scaleup, temp;
  2920. // GENERATE RANDOM VALUES WITHIN RANGE 0 to 1
  2921. while(!gotit) {
  2922. maxrand = 0.0;
  2923. minrand = 1.0;
  2924. for(n=0;n < streamcnt;n++) {
  2925. turbpset[n] = drand48();
  2926. minrand = min(minrand,turbpset[n]);
  2927. maxrand = max(maxrand,turbpset[n]);
  2928. }
  2929. if(maxrand > minrand) // Ensure there's not a zero-spread of rand-values
  2930. gotit = 1;
  2931. }
  2932. randrange = maxrand - minrand;
  2933. scaleup = pitchrange/randrange;
  2934. // SORT INTO ASCENDING ORDER
  2935. for(n=0;n < streamcnt-1;n++) {
  2936. for(m=n+1;m < streamcnt;m++) {
  2937. if(turbpset[m] < turbpset[n]) {
  2938. temp = turbpset[n];
  2939. turbpset[n] = turbpset[m];
  2940. turbpset[m] = temp;
  2941. }
  2942. }
  2943. }
  2944. // SCALE TO PITCHRANGE
  2945. for(n=0;n < streamcnt;n++) {
  2946. turbpset[n] -= minrand; // Move randomvalues into 0 - randrange
  2947. turbpset[n] *= scaleup; // Scale to full pitchrange
  2948. turbpset[n] += pitchbot; // Put in actual pitch values
  2949. }
  2950. turbulent_bandswap(perm,streamcnt); // Permute order of streams, so all bands cross
  2951. for(n=0;n < streamcnt;n++) // Assign the pitches to the bands
  2952. turbpitch[perm[n]] = turbpset[n];
  2953. }
  2954. /************************************ PANCALC *******************************/
  2955. void pancalc(double position,double *leftgain,double *rightgain)
  2956. {
  2957. int dirflag;
  2958. double temp;
  2959. double relpos;
  2960. double reldist, invsquare;
  2961. if(position < 0.0)
  2962. dirflag = SIGNAL_TO_LEFT; /* signal on left */
  2963. else
  2964. dirflag = SIGNAL_TO_RIGHT;
  2965. if(position < 0)
  2966. relpos = -position;
  2967. else
  2968. relpos = position;
  2969. if(relpos <= 1.0){ /* between the speakers */
  2970. temp = 1.0 + (relpos * relpos);
  2971. reldist = ROOT2 / sqrt(temp);
  2972. temp = (position + 1.0) / 2.0;
  2973. *rightgain = temp * reldist;
  2974. *leftgain = (1.0 - temp ) * reldist;
  2975. } else { /* outside the speakers */
  2976. temp = (relpos * relpos) + 1.0;
  2977. reldist = sqrt(temp) / ROOT2; /* relative distance to source */
  2978. invsquare = 1.0 / (reldist * reldist);
  2979. if(dirflag == SIGNAL_TO_LEFT){
  2980. *leftgain = invsquare;
  2981. *rightgain = 0.0;
  2982. } else { /* SIGNAL_TO_RIGHT */
  2983. *rightgain = invsquare;
  2984. *leftgain = 0;
  2985. }
  2986. }
  2987. }
  2988. /************************** HANDLE_THE_SPECIAL_DATA **********************************/
  2989. int handle_the_special_data(int *cmdlinecnt,char ***cmdline,int *threadvalscnt,dataptr dz)
  2990. {
  2991. int cnt, *i, idummy;
  2992. char *filename = (*cmdline)[0];
  2993. FILE *fp;
  2994. double dummy;
  2995. char temp[200], *q;
  2996. if((fp = fopen(filename,"r"))==NULL) {
  2997. sprintf(errstr, "Can't open data file %s to read data.\n",filename);
  2998. return(DATA_ERROR);
  2999. }
  3000. cnt = 0;
  3001. while(fgets(temp,200,fp)==temp) {
  3002. q = temp;
  3003. if(*q == ';') // Allow comments in file
  3004. continue;
  3005. while(get_float_from_within_string(&q,&dummy)) {
  3006. idummy = (int)round(dummy);
  3007. if(idummy < 2 || idummy > 100) {
  3008. sprintf(errstr,"Invalid thread count (%d) in file %s (Valid Range 2 - 100)\n",idummy,filename);
  3009. return(MEMORY_ERROR);
  3010. }
  3011. cnt++;
  3012. }
  3013. }
  3014. if(cnt == 0) {
  3015. sprintf(errstr,"No data in data file %s\n",filename);
  3016. return(DATA_ERROR);
  3017. }
  3018. if((dz->iparray = (int **)malloc(sizeof(int *)))==NULL) {
  3019. sprintf(errstr,"INSUFFICIENT MEMORY for input data in file %s.\n",filename);
  3020. return(MEMORY_ERROR);
  3021. }
  3022. if((dz->iparray[0] = (int *)malloc(cnt * sizeof(int)))==NULL) {
  3023. sprintf(errstr,"INSUFFICIENT MEMORY for input data in file %s.\n",filename);
  3024. return(MEMORY_ERROR);
  3025. }
  3026. fseek(fp,0,0);
  3027. i = dz->iparray[0];
  3028. while(fgets(temp,200,fp)==temp) {
  3029. q = temp;
  3030. if(*q == ';') // Allow comments in file
  3031. continue;
  3032. while(get_float_from_within_string(&q,&dummy)) {
  3033. *i = (int)round(dummy);
  3034. i++;
  3035. }
  3036. }
  3037. if(fclose(fp)<0) {
  3038. fprintf(stdout,"WARNING: Failed to close file %s.\n",filename);
  3039. fflush(stdout);
  3040. }
  3041. *threadvalscnt = cnt;
  3042. (*cmdline)++;
  3043. (*cmdlinecnt)--;
  3044. return(FINISHED);
  3045. }