| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314 |
- /*
- * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
- * http://www.trevorwishart.co.uk
- * http://www.composersdesktop.com
- *
- This file is part of the CDP System.
- The CDP System is free software; you can redistribute it
- and/or modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- The CDP System is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with the CDP System; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
- *
- */
- // Attempted to integrate a "-b" flag that synthesizes the bands
- // One after another (rather trhan superimposed)
- // NEED TO TEST HIS WORKS (and test orig not broken)
- // This code saved on STICK
- // ORIG_CODE saved as strand_orig.c ***
- #include <stdio.h>
- #include <stdlib.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <pnames.h>
- #include <filetype.h>
- #include <processno.h>
- #include <modeno.h>
- #include <logic.h>
- #include <globcon.h>
- #include <cdpmain.h>
- #include <math.h>
- #include <mixxcon.h>
- #include <osbind.h>
- #include <science.h>
- #include <standalone.h>
- #include <ctype.h>
- #include <sfsys.h>
- #include <string.h>
- #include <srates.h>
- #ifdef unix
- #include <aaio.h>
- #endif
- #define STRAND_SRATE (44100)
- #define STRAND_MAXWARP (3) // Max timewarp, takes 0-1 line and, at max(min) cubes (or cube-roots) values,
- // to give concave or convex distortion of 0-1 value line.
- #define WAVYFRAC (0.4) // Boundary of band, during wavy-band-turbulence, can wander to max of 2/5 of bandwidth up or down.
- #define TURBPOW (0.5) // Random 0-1 LEVEL values, raised to this power, to weight them towards louder vals dominating
- #define TURBFLATTEN (2.0) // As turbulence kicks in (in range 0 -> 1), any waviness of band boundaries flattens out.
- // Amplitude of waves is related to value of (1 - turbulence), (range 1 -> 0)
- // The straight line of this function is made concave by this power factor
- // So amplitude dips more quickly towards zero at start of any turbulence.
- #define splicesize rampbrksize
- #define datasize temp_sampsize
- #define subbanded is_mapping
- #define derivs is_transpos
- #define rotmix is_transpos
- #define sintable is_rectified
- #define costable specenv_type
- #define sinptrs zeroset
- #define frqstores fzeroset
- #define tessitura is_flat
- #define scaler is_sharp
- #define rotlevel could_be_pitch
- #define levderivs could_be_transpos
- #define flowdata descriptor_samps
- #define flowcnt ringsize
- #define twist dz->brk[STRAND_TWIST]
- #define LAMINAR 0
- #define TOTWIST 1
- #define FROMTWIST 2
- #define TWISTED 3
- #define ROOT2 (1.4142136)
- #define SIGNAL_TO_LEFT (0)
- #define SIGNAL_TO_RIGHT (1)
- #ifdef unix
- #define round(x) lround((x))
- #endif
- char errstr[2400];
- int anal_infiles = 1;
- int sloom = 0;
- int sloombatch = 0;
- const char* cdp_version = "7.0.0";
- //CDP LIB REPLACEMENTS
- static int setup_strands_application(dataptr dz);
- static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
- static int setup_strands_param_ranges_and_defaults(dataptr dz);
- static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
- static int open_the_outfile(char *sfnam,dataptr dz);
- static int setup_and_init_input_param_activity(dataptr dz,int tipc);
- static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
- static int establish_application(dataptr dz);
- static int initialise_vflags(dataptr dz);
- static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
- static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
- static int mark_parameter_types(dataptr dz,aplptr ap);
- static int assign_file_data_storage(int infilecnt,dataptr dz);
- static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
- static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
- static int get_the_mode_from_cmdline(char *str,dataptr dz);
- static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
- static int strands_param_preprocess(double *pitchrange,double *band_separation,double *tessitura,int *isturb,int threadvalscnt,dataptr dz);
- static int synthesis(dataptr dz);
- //static void incr_sinptr(int n,double time,double onehzincr,dataptr dz);
- //static double read_level(int n,double time,dataptr dz);
- static int create_strands_sndbufs(dataptr dz);
- static int spline(int streamno,int islevel,dataptr dz);
- static double splint(int streamno,double time,int islevel,dataptr dz);
- static int create_next_outfile(int no, char *sfnam, char *temp,dataptr dz);
- static void scatter_streamdata_in_last_cycle(double time,int bandno,int threadscnt,int threadbas, int outcnt,double lastcycendtime,dataptr dz);
- static double wavy(int bandno,double bandtop_mean,double tessitura,double amp,double *wavyfrq,double *tabpos,int *cycend,double scaling,dataptr dz);
- static int establish_flow_types(dataptr dz);
- static int get_flow_type(double time,double *transitstart,double *twistreffrq,double *transittime,dataptr dz) ;
- static double turblevel(double turbulence,double thislevel,dataptr dz);
- static int check_turbulence_values(int *isturb,dataptr dz);
- static void assign_turbulence_pitches(int streamcnt,double pitchbot,double pitchrange,int *perm,double *turbpset,double *turbpitch);
- static void pancalc(double position,double *leftgain,double *rightgain);
- static double sinread(int iscos,double *tabpos,double frq,int *cycend,double scaling,dataptr dz);
- static int strands(double pitchrange,double band_separation,double tessitura,int isturb,dataptr dz);
- static int output_strands(char *sfnam,dataptr dz);
- static int handle_the_special_data(int *cmdlinecnt,char ***cmdline,int *threadvalscnt,dataptr dz);
- /**************************************** MAIN *********************************************/
- int main(int argc,char *argv[])
- {
- int exit_status;
- dataptr dz = NULL;
- char **cmdline, sfnam[400];
- int cmdlinecnt, k, isturb = 0, threadvalscnt = 0;
- double pitchrange, band_separation, tessitura;
- aplptr ap;
- int is_launched = FALSE;
- if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
- fprintf(stdout,"%s\n",cdp_version);
- fflush(stdout);
- return 0;
- }
- /* CHECK FOR SOUNDLOOM */
- if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
- sloom = 0;
- sloombatch = 1;
- }
- if(sflinit("cdp")){
- sfperror("cdp: initialisation\n");
- return(FAILED);
- }
- /* SET UP THE PRINCIPLE DATASTRUCTURE */
- if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if(!sloom) {
- if(argc == 1) {
- usage1();
- return(FAILED);
- } else if(argc == 2) {
- usage2(argv[1]);
- return(FAILED);
- }
- }
- if(!sloom) {
- if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- cmdline = argv;
- cmdlinecnt = argc;
- if((get_the_process_no(argv[0],dz))<0)
- return(FAILED);
- cmdline++;
- cmdlinecnt--;
- dz->maxmode = 3;
- if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(exit_status);
- }
- cmdline++;
- cmdlinecnt--;
- // setup_particular_application =
- if((exit_status = setup_strands_application(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- } else {
- //parse_TK_data() =
- if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(exit_status);
- }
- }
- ap = dz->application;
- dz->infile->channels = 2;
- dz->infile->srate = STRAND_SRATE;
- // parse_infile_and_hone_type() =
- // setup_param_ranges_and_defaults() =
- if((exit_status = setup_strands_param_ranges_and_defaults(dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // open_first_infile() : redundant
- // handle_extra_infiles() : redundant
- // handle_outfile() =
- if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // handle_formants() redundant
- // handle_formant_quiksearch() redundant
- strcpy(sfnam,dz->outfilename);
- if(sloom) {
- k = strlen(sfnam);
- k--;
- *(sfnam + k) = ENDOFSTR; // (shorten generic filename by 1 cyaracter, discarding "0"
- }
- if(dz->mode == 2) {
- if((exit_status = handle_the_special_data(&cmdlinecnt,&cmdline,&threadvalscnt,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- }
- if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if(dz->iparam[STRAND_SEED] > 0) {
- srand((int)dz->iparam[STRAND_SEED]);
- }
- // check_param_validity_and_consistency() redundant
- is_launched = TRUE;
- if(dz->mode == 1) {
- if((exit_status = create_strands_sndbufs(dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- }
- if((exit_status = strands_param_preprocess(&pitchrange,&band_separation,&tessitura,&isturb,threadvalscnt,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if(EVEN(dz->mode) && !sloom)
- strcat(dz->outfilename,"0.txt");
- if((exit_status = open_the_outfile(dz->outfilename,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // process_file =
- if((exit_status = strands(pitchrange,band_separation,tessitura,isturb,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if(dz->mode == 1) {
- if((exit_status = synthesis(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- } else {
- if((exit_status = output_strands(sfnam,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- }
- if((exit_status = complete_output(dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
- free(dz);
- return(SUCCEEDED);
- }
- /**********************************************
- REPLACED CDP LIB FUNCTIONS
- **********************************************/
- /****************************** SET_PARAM_DATA *********************************/
- int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
- {
- ap->special_data = (char)special_data;
- ap->param_cnt = (char)paramcnt;
- ap->max_param_cnt = (char)maxparamcnt;
- if(ap->max_param_cnt>0) {
- if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->param_list,paramlist);
- }
- return(FINISHED);
- }
- /****************************** SET_VFLGS *********************************/
- int set_vflgs
- (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
- {
- ap->option_cnt = (char) optcnt; /*RWD added cast */
- if(optcnt) {
- if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->option_list,optlist);
- if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->option_flags,optflags);
- }
- ap->vflag_cnt = (char) vflagcnt;
- ap->variant_param_cnt = (char) vparamcnt;
- if(vflagcnt) {
- if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->variant_list,varlist);
- if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->variant_flags,varflags);
- }
- return(FINISHED);
- }
- /***************************** APPLICATION_INIT **************************/
- int application_init(dataptr dz)
- {
- int exit_status;
- int storage_cnt;
- int tipc, brkcnt;
- aplptr ap = dz->application;
- if(ap->vflag_cnt>0)
- initialise_vflags(dz);
- tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
- ap->total_input_param_cnt = (char)tipc;
- if(tipc>0) {
- if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
- return(exit_status);
- if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
- return(exit_status);
- if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
- return(exit_status);
- }
- brkcnt = tipc;
- //THERE ARE NO INPUTFILE brktables USED IN THIS PROCESS
- if(brkcnt>0) {
- if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
- return(exit_status);
- }
- if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
- if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
- return(exit_status);
- if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
- return(exit_status);
- }
- if((exit_status = mark_parameter_types(dz,ap))<0)
- return(exit_status);
-
- // establish_infile_constants() replaced by
- dz->infilecnt = 1;
- //establish_bufptrs_and_extra_buffers():
- return(FINISHED);
- }
- /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
- /* RWD mallo changed to calloc; helps debug verison run as release! */
- int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
- {
- if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
- return(MEMORY_ERROR);
- }
- if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
- return(MEMORY_ERROR);
- }
- if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
- return(MEMORY_ERROR);
- }
- if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
- int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
- {
- int n;
- for(n=0;n<storage_cnt;n++) {
- dz->is_int[n] = (char)0;
- dz->no_brk[n] = (char)0;
- }
- return(FINISHED);
- }
- /***************************** MARK_PARAMETER_TYPES **************************/
- int mark_parameter_types(dataptr dz,aplptr ap)
- {
- int n, m; /* PARAMS */
- for(n=0;n<ap->max_param_cnt;n++) {
- switch(ap->param_list[n]) {
- case('0'): break; /* dz->is_active[n] = 0 is default */
- case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
- case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
- case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
- case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
- default:
- sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- } /* OPTIONS */
- for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
- switch(ap->option_list[n]) {
- case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
- case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
- default:
- sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- } /* VARIANTS */
- for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
- switch(ap->variant_list[n]) {
- case('0'): break;
- case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
- case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
- default:
- sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- } /* INTERNAL */
- for(n=0,
- m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
- switch(ap->internal_param_list[n]) {
- case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
- case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('d'): dz->no_brk[m] = (char)1; break;
- default:
- sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- }
- return(FINISHED);
- }
- /************************ HANDLE_THE_OUTFILE *********************/
- int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
- {
- char *filename = (*cmdline)[0], *p;
- if(filename[0]=='-' && filename[1]=='f') {
- dz->floatsam_output = 1;
- dz->true_outfile_stype = SAMP_FLOAT;
- filename+= 2;
- }
- if(!sloom) {
- if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
- sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
- return(DATA_ERROR);
- }
- }
- p = filename; // Drop file extension
- while(*p != ENDOFSTR) {
- if(*p == '.') {
- *p = ENDOFSTR;
- break;
- }
- p++;
- }
- strcpy(dz->outfilename,filename);
- (*cmdline)++;
- (*cmdlinecnt)--;
- return(FINISHED);
- }
- /************************ OPEN_THE_OUTFILE *********************/
- int open_the_outfile(char *sfnam,dataptr dz)
- {
- int exit_status;
- if(!sloom && dz->mode == 1)
- strcat(sfnam,"0");
- if((exit_status = create_sized_outfile(sfnam,dz))<0)
- return(exit_status);
- return(FINISHED);
- }
- /***************************** ESTABLISH_APPLICATION **************************/
- int establish_application(dataptr dz)
- {
- aplptr ap;
- if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
- sprintf(errstr,"establish_application()\n");
- return(MEMORY_ERROR);
- }
- ap = dz->application;
- memset((char *)ap,0,sizeof(struct applic));
- return(FINISHED);
- }
- /************************* INITIALISE_VFLAGS *************************/
- int initialise_vflags(dataptr dz)
- {
- int n;
- if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->application->vflag_cnt;n++)
- dz->vflag[n] = FALSE;
- return FINISHED;
- }
- /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
- int setup_input_param_defaultval_stores(int tipc,aplptr ap)
- {
- int n;
- if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<tipc;n++)
- ap->default_val[n] = 0.0;
- return(FINISHED);
- }
- /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
- int setup_and_init_input_param_activity(dataptr dz,int tipc)
- {
- int n;
- if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
- sprintf(errstr,"setup_and_init_input_param_activity()\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<tipc;n++)
- dz->is_active[n] = (char)0;
- return(FINISHED);
- }
- /************************* SETUP_STRANDS_APPLICATION *******************/
- int setup_strands_application(dataptr dz)
- {
- int exit_status;
- aplptr ap;
- if((exit_status = establish_application(dz))<0) // GLOBAL
- return(FAILED);
- ap = dz->application;
- // SEE parstruct FOR EXPLANATION of next 2 functions
- if(dz->mode == 2) {
- if((exit_status = set_param_data(ap,COUTHREADS,14,13,"di0dddDDDDDDDi"))<0)
- return(FAILED);
- } else {
- if((exit_status = set_param_data(ap,0,14,14,"diidddDDDDDDDi"))<0)
- return(FAILED);
- }
- if(dz->mode == 0 || dz->mode == 2) {
- if((exit_status = set_vflgs(ap,"gmf",3,"ddi","",0,0,""))<0)
- return(exit_status);
- } else {
- if((exit_status = set_vflgs(ap,"gmf",3,"ddi","s",1,0,"0"))<0)
- return(exit_status);
- }
- dz->input_data_type = NO_FILE_AT_ALL;
- switch(dz->mode) {
- case(0):
- case(2):
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- case(1):
- dz->process_type = UNEQUAL_SNDFILE;
- dz->outfiletype = SNDFILE_OUT;
- break;
- }
- // set_legal_infile_structure -->
- dz->has_otherfile = FALSE;
- // assign_process_logic -->
- return application_init(dz); //GLOBAL
- }
- /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
- int parse_infile_and_check_type(char **cmdline,dataptr dz)
- {
- int exit_status;
- infileptr infile_info;
- if(!sloom) {
- if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
- return(MEMORY_ERROR);
- } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
- sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
- return(PROGRAM_ERROR);
- } else if(infile_info->filetype != SNDFILE) {
- sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
- return(DATA_ERROR);
- } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
- sprintf(errstr,"Failed to copy file parsing information\n");
- return(PROGRAM_ERROR);
- }
- free(infile_info);
- }
- return(FINISHED);
- }
- /************************* SETUP_STRANDS_PARAM_RANGES_AND_DEFAULTS *******************/
- int setup_strands_param_ranges_and_defaults(dataptr dz)
- {
- int exit_status;
- aplptr ap = dz->application;
- // set_param_ranges()
- ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
- // NB total_input_param_cnt is > 0 !!!
- if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
- return(FAILED);
- // get_param_ranges()
- ap->lo[STRAND_DUR] = 0.0;
- ap->hi[STRAND_DUR] = 32767.0;
- ap->default_val[STRAND_DUR] = 10.0;
- ap->lo[STRAND_BANDS] = 1;
- ap->hi[STRAND_BANDS] = 16;
- ap->default_val[STRAND_BANDS] = 4;
- if(dz->mode != 2) {
- ap->lo[STRAND_THRDS] = 2;
- ap->hi[STRAND_THRDS] = 100;
- ap->default_val[STRAND_THRDS] = 3;
- }
- ap->lo[STRAND_TSTEP] = 1;
- ap->hi[STRAND_TSTEP] = 500;
- ap->default_val[STRAND_TSTEP] = 100;
- ap->lo[STRAND_BOT] = 0;
- ap->hi[STRAND_BOT] = 127;
- ap->default_val[STRAND_BOT] = 36;
- ap->lo[STRAND_TOP] = 0;
- ap->hi[STRAND_TOP] = 127;
- ap->default_val[STRAND_TOP] = 84;
- ap->lo[STRAND_TWIST] = 0;
- ap->hi[STRAND_TWIST] = 10;
- ap->default_val[STRAND_TWIST] = 3;
- ap->lo[STRAND_RAND] = 0;
- ap->hi[STRAND_RAND] = 1;
- ap->default_val[STRAND_RAND] = 0;
- ap->lo[STRAND_SCAT] = 0;
- ap->hi[STRAND_SCAT] = 1;
- ap->default_val[STRAND_SCAT] = 0;
- ap->lo[STRAND_VAMP] = 0;
- ap->hi[STRAND_VAMP] = 1;
- ap->default_val[STRAND_VAMP] = 0;
- ap->lo[STRAND_VMIN] = 0;
- ap->hi[STRAND_VMIN] = 4;
- ap->default_val[STRAND_VMIN] = 0;
- ap->lo[STRAND_VMAX] = 0;
- ap->hi[STRAND_VMAX] = 4;
- ap->default_val[STRAND_VMAX] = 0;
- ap->lo[STRAND_TURB] = 0;
- ap->hi[STRAND_TURB] = 2;
- ap->default_val[STRAND_TURB] = 0;
- ap->lo[STRAND_SEED] = 0;
- ap->hi[STRAND_SEED] = 256;
- ap->default_val[STRAND_SEED] = 0;
- ap->lo[STRAND_GAP] = 0;
- ap->hi[STRAND_GAP] = 12;
- ap->default_val[STRAND_GAP] = 0;
- ap->lo[STRAND_MINB] = 1;
- ap->hi[STRAND_MINB] = 24;
- ap->default_val[STRAND_MINB] = 12;
- ap->lo[STRAND_3D] = -1;
- ap->hi[STRAND_3D] = 1;
- ap->default_val[STRAND_3D] = 0;
- dz->maxmode = 3;
- if(!sloom)
- put_default_vals_in_all_params(dz);
- return(FINISHED);
- }
- /********************************* PARSE_SLOOM_DATA *********************************/
- int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
- {
- int exit_status;
- int cnt = 1, infilecnt;
- int filesize, insams, inbrksize;
- double dummy;
- int true_cnt = 0;
- aplptr ap;
- while(cnt<=PRE_CMDLINE_DATACNT) {
- if(cnt > argc) {
- sprintf(errstr,"Insufficient data sent from TK\n");
- return(DATA_ERROR);
- }
- switch(cnt) {
- case(1):
- if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
- sprintf(errstr,"Cannot read process no. sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(2):
- if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
- sprintf(errstr,"Cannot read mode no. sent from TK\n");
- return(DATA_ERROR);
- }
- if(dz->mode > 0)
- dz->mode--;
- //setup_particular_application() =
- if((exit_status = setup_strands_application(dz))<0)
- return(exit_status);
- ap = dz->application;
- break;
- case(3):
- if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
- sprintf(errstr,"Cannot read infilecnt sent from TK\n");
- return(DATA_ERROR);
- }
- if(infilecnt < 1) {
- true_cnt = cnt + 1;
- cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
- }
- if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
- return(exit_status);
- break;
- case(INPUT_FILETYPE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
- sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
- return(DATA_ERROR);
- }
- break;
- case(INPUT_FILESIZE+4):
- if(sscanf(argv[cnt],"%d",&filesize)!=1) {
- sprintf(errstr,"Cannot read infilesize sent from TK\n");
- return(DATA_ERROR);
- }
- dz->insams[0] = filesize;
- break;
- case(INPUT_INSAMS+4):
- if(sscanf(argv[cnt],"%d",&insams)!=1) {
- sprintf(errstr,"Cannot read insams sent from TK\n");
- return(DATA_ERROR);
- }
- dz->insams[0] = insams;
- break;
- case(INPUT_SRATE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
- sprintf(errstr,"Cannot read srate sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_CHANNELS+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
- sprintf(errstr,"Cannot read channels sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_STYPE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
- sprintf(errstr,"Cannot read stype sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ORIGSTYPE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
- sprintf(errstr,"Cannot read origstype sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ORIGRATE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
- sprintf(errstr,"Cannot read origrate sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MLEN+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
- sprintf(errstr,"Cannot read Mlen sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DFAC+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
- sprintf(errstr,"Cannot read Dfac sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ORIGCHANS+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
- sprintf(errstr,"Cannot read origchans sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_SPECENVCNT+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
- sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
- return(DATA_ERROR);
- }
- dz->specenvcnt = dz->infile->specenvcnt;
- break;
- case(INPUT_WANTED+4):
- if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
- sprintf(errstr,"Cannot read wanted sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_WLENGTH+4):
- if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
- sprintf(errstr,"Cannot read wlength sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_OUT_CHANS+4):
- if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
- sprintf(errstr,"Cannot read out_chans sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- /* RWD these chanegs to samps - tk will have to deal with that! */
- case(INPUT_DESCRIPTOR_BYTES+4):
- if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
- sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_IS_TRANSPOS+4):
- if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
- sprintf(errstr,"Cannot read is_transpos sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_COULD_BE_TRANSPOS+4):
- if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
- sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_COULD_BE_PITCH+4):
- if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
- sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DIFFERENT_SRATES+4):
- if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
- sprintf(errstr,"Cannot read different_srates sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DUPLICATE_SNDS+4):
- if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
- sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_BRKSIZE+4):
- if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
- sprintf(errstr,"Cannot read brksize sent from TK\n");
- return(DATA_ERROR);
- }
- if(inbrksize > 0) {
- switch(dz->input_data_type) {
- case(WORDLIST_ONLY):
- break;
- case(PITCH_AND_PITCH):
- case(PITCH_AND_TRANSPOS):
- case(TRANSPOS_AND_TRANSPOS):
- dz->tempsize = inbrksize;
- break;
- case(BRKFILES_ONLY):
- case(UNRANGED_BRKFILE_ONLY):
- case(DB_BRKFILES_ONLY):
- case(ALL_FILES):
- case(ANY_NUMBER_OF_ANY_FILES):
- if(dz->extrabrkno < 0) {
- sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
- return(DATA_ERROR);
- }
- if(dz->brksize == NULL) {
- sprintf(errstr,"CDP has not established storage space for input brktable.\n");
- return(PROGRAM_ERROR);
- }
- dz->brksize[dz->extrabrkno] = inbrksize;
- break;
- default:
- sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
- dz->input_data_type);
- return(PROGRAM_ERROR);
- }
- break;
- }
- break;
- case(INPUT_NUMSIZE+4):
- if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
- sprintf(errstr,"Cannot read numsize sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_LINECNT+4):
- if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
- sprintf(errstr,"Cannot read linecnt sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ALL_WORDS+4):
- if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
- sprintf(errstr,"Cannot read all_words sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ARATE+4):
- if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
- sprintf(errstr,"Cannot read arate sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_FRAMETIME+4):
- if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
- sprintf(errstr,"Cannot read frametime sent from TK\n");
- return(DATA_ERROR);
- }
- dz->frametime = (float)dummy;
- break;
- case(INPUT_WINDOW_SIZE+4):
- if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
- sprintf(errstr,"Cannot read window_size sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_NYQUIST+4):
- if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
- sprintf(errstr,"Cannot read nyquist sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DURATION+4):
- if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
- sprintf(errstr,"Cannot read duration sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MINBRK+4):
- if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
- sprintf(errstr,"Cannot read minbrk sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MAXBRK+4):
- if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
- sprintf(errstr,"Cannot read maxbrk sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MINNUM+4):
- if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
- sprintf(errstr,"Cannot read minnum sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MAXNUM+4):
- if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
- sprintf(errstr,"Cannot read maxnum sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- default:
- sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
- return(PROGRAM_ERROR);
- }
- cnt++;
- }
- if(cnt!=PRE_CMDLINE_DATACNT+1) {
- sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
- return(DATA_ERROR);
- }
- if(true_cnt)
- cnt = true_cnt;
- *cmdlinecnt = 0;
- while(cnt < argc) {
- if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
- return(exit_status);
- cnt++;
- }
- return(FINISHED);
- }
- /********************************* GET_TK_CMDLINE_WORD *********************************/
- int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
- {
- if(*cmdlinecnt==0) {
- if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
- return(MEMORY_ERROR);
- }
- } else {
- if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
- return(MEMORY_ERROR);
- }
- }
- if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
- return(MEMORY_ERROR);
- }
- strcpy((*cmdline)[*cmdlinecnt],q);
- (*cmdlinecnt)++;
- return(FINISHED);
- }
- /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
- int assign_file_data_storage(int infilecnt,dataptr dz)
- {
- int exit_status;
- int no_sndfile_system_files = FALSE;
- dz->infilecnt = infilecnt;
- if((exit_status = allocate_filespace(dz))<0)
- return(exit_status);
- if(no_sndfile_system_files)
- dz->infilecnt = 0;
- return(FINISHED);
- }
- /************************* redundant functions: to ensure libs compile OK *******************/
- int assign_process_logic(dataptr dz)
- {
- return(FINISHED);
- }
- void set_legal_infile_structure(dataptr dz)
- {}
- int set_legal_internalparam_structure(int process,int mode,aplptr ap)
- {
- return(FINISHED);
- }
- int setup_internal_arrays_and_array_pointers(dataptr dz)
- {
- return(FINISHED);
- }
- int establish_bufptrs_and_extra_buffers(dataptr dz)
- {
- return(FINISHED);
- }
- int read_special_data(char *str,dataptr dz)
- {
- return(FINISHED);
- }
- int inner_loop
- (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
- {
- return(FINISHED);
- }
- int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
- {
- return(FINISHED);
- }
- /******************************** USAGE1 ********************************/
- int usage1(void)
- {
- usage2("strands");
- return(USAGE_ONLY);
- }
- /********************************************************************************************/
- int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
- {
- if(!strcmp(prog_identifier_from_cmdline,"strands")) dz->process = STRANDS;
- else {
- fprintf(stderr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
- return(USAGE_ONLY);
- }
- return(FINISHED);
- }
- /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
- int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
- {
- int n;
- if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
- return(MEMORY_ERROR);
- }
- if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
- return(MEMORY_ERROR);
- }
- if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
- return(MEMORY_ERROR);
- }
- if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
- return(MEMORY_ERROR);
- }
- if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
- return(MEMORY_ERROR);
- }
- if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
- return(MEMORY_ERROR);
- }
- if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<brkcnt;n++) {
- dz->brk[n] = NULL;
- dz->brkptr[n] = NULL;
- dz->brkinit[n] = 0;
- dz->brksize[n] = 0;
- }
- return(FINISHED);
- }
- /******************************** USAGE2 ********************************/
- int usage2(char *str)
- {
- if(!strcmp(str,"strands")) {
- fprintf(stderr,
- "USAGE: strands strands 1 generic_outdatafilename ...\n"
- "OR: strands strands 2 outsndfilename ...\n"
- "dur bands threads tstep bot top twist rand scat vamp vmin vmax turb seed\n"
- "[-ggap] [-mminband] [-f3d] [-s]\n"
- "\n"
- "OR: strands strands 3 generic_outdatafilename ...\n"
- "thrdsfile dur bands tstep bot top twist rand scat vamp vmin vmax turb seed\n"
- "[-ggap] [-mminband] [-f3d] [-s]\n"
- "\n"
- "Generate pitch-data for several streams (or the combined sound itself)\n"
- "where total pitch-tessitura divided into equal-sized pitch-BANDS\n"
- "and each band made of pitch-line THREADS, cycling around one-another\n"
- "pitchwise, within the band, IF twist strays from zero.\n"
- "Strands in adjacent bands spiral in opposite directions.\n"
- "\n"
- "DUR Duration of output data or sound.\n"
- "BANDS Number of bands in the output.\n"
- "THREADS Number of sounds in a band.\n"
- "THRDSFILE Textfile listing number of sounds in EACH band.\n"
- "TSTEP Timestep (in mS) between pitch-data vals in output.\n"
- "BOT Lowest pitch of all output.\n"
- "TOP Highest pitch of all output.\n"
- "TWIST Rate of cycling of output pitches in bands (Hz).\n"
- "RAND Random variation of twist frq from band to band.\n"
- "SCAT Random-warp of cycles of threads in same band.\n"
- "VORTEX WAVINESS\n"
- "VAMP ammount band-boundaries wander from fixed frqs.\n"
- "VMIN min rate of oscillation of band boundaries.\n"
- "VMAX max rate of oscillation of band boundaries.\n"
- "TURBULENCE\n"
- "TURB 0 none: >0-to-1 turbulence in bands: >1-to-2 gobal turbulence.\n"
- "SEED Seed value for randomisation settings.\n"
- "GAP Minimum pitch-gap between bands.\n"
- "MINBAND Minimum pitchwidth of any band.\n"
- "3D Motion in 3D: 0 = none: 1 = bottom band up at front: -1 = down.\n"
- "\n"
- "-s (Mode 2 only) - outputs each band in succesion.\n"
- "\n"
- "Press any key to see further information.\n");
- while(!kbhit())
- ;
- if(kbhit()) {
- fprintf(stderr,
- "\n"
- "TWIST & With twist ZERO, streams do not cycle round one another\n"
- "LAMINAR but stay at steady(ish) pitches .. (\"laminar flow\").\n"
- "FLOW To force laminar flow, use 2 adjacent brkpnt vals of zero\n"
- " (laminar flow is forced between the associated times).\n"
- " To move to twisted flow, follow a zero val by a non-zero val.\n"
- " To maintain twisted flow, follow non-zero val by non-zero val.\n"
- " To untwist the flow, follow a non-zero val by a zero val.\n"
- " \n"
- " During laminar flow,\n"
- " \"RAND\" controls pitch-jitter of laminae.\n"
- " \"SCAT\" controls level-jitter of laminae.\n"
- " \n"
- "3D Outputs 2 extra param sets for each stream.\n"
- " 1st set can control loudness, or synth partial-cnt\n"
- " in creation of a synthesized output.\n"
- " 2nd set can control a mix with reverb (etc) version,\n"
- " (parameter is level of modified source in that mix)\n"
- " both to simulate distance from the listener.\n"
- " In modes 1 & 3, this extra data is output in separate files\n"
- " AFTER all the pitchdata files have been output.\n"
- " The output order is ...\n"
- " all pitch data, all 1st controlfiles, all 2nd controlfiles.\n"
- "\n"
- "TURBULENT This can only happen (turb > 0.0) when twist > 0.0\n"
- "FLOW (i.e. there can be no turbulence during laminar flow\n"
- " or in the transitions to and from twisted flow).\n"
- "\n"
- "MODE 2 SOUND OUTPUT\n"
- " Intended only as sound-test for the data output in mode 1.\n"
- " Bands are output, equally spaced, across the stereo stage.\n"
- "\n");
- }
- } else
- fprintf(stdout,"Unknown option '%s'\n",str);
- return(USAGE_ONLY);
- }
- int usage3(char *str1,char *str2)
- {
- fprintf(stderr,"Insufficient parameters on command line.\n");
- return(USAGE_ONLY);
- }
- /**************************** STRANDS_PARAM_PREPROCESS *************************
- *
- * Arrays 0 to N-1 store the stream frq information at each timestep.
- * Array N stores the simetable.
- * Array N+1 store sintable-pointer values for each stream being synthesized.
- */
- int strands_param_preprocess(double *pitchrange,double *band_separation,double *tessitura,int *isturb,int threadvalscnt,dataptr dz)
- {
- int exit_status, synth_arrays = 0, rotation_arrays = 0, universal_arrays;
- int n;
- double srate, endsplice, gaps;
- double *sintab, *costab;
- // Setup global params
-
- dz->param[STRAND_TSTEP] *= MS_TO_SECS;
- dz->datasize = (int)ceil(dz->param[STRAND_DUR]/dz->param[STRAND_TSTEP]) + 1; // Size of data output depends on timestep used
- if(dz->mode == 2) {
- if(threadvalscnt != dz->iparam[STRAND_BANDS]) {
- sprintf(errstr,"NUMBER OF THREAD COUNTS in data file (%d) does not tally with band count (%d).\n",threadvalscnt,dz->iparam[STRAND_BANDS]);
- return(MEMORY_ERROR);
- }
- dz->itemcnt = 0;
- for(n=0;n<dz->iparam[STRAND_BANDS];n++)
- dz->itemcnt += dz->iparray[0][n];
- } else
- dz->itemcnt = dz->iparam[STRAND_THRDS] * dz->iparam[STRAND_BANDS]; // No of threads in output
- dz->scalefact = (double)SYNTH_TABSIZE/(double)STRAND_SRATE; // Scales reading of sintab to sound-output samplerate
- dz->scaler = (double)SYNTH_TABSIZE * dz->param[STRAND_TSTEP]; // Scales reading of sintab to output-data "sample-rate"
- // Setup effective bandwidths
- *pitchrange = dz->param[STRAND_TOP] - dz->param[STRAND_BOT]; // Total pitchrange used
- if(*pitchrange <= 0) {
- sprintf(errstr,"Invalid pitch range (<= 0.0).\n");
- return(DATA_ERROR);
- }
- *band_separation = *pitchrange/(double)dz->param[STRAND_BANDS]; // Separation is distance between bands (prior to any gapping)
- gaps = dz->param[STRAND_GAP] * (dz->param[STRAND_BANDS] - 1);
- if(*pitchrange - gaps <= 0.0) {
- sprintf(errstr,"Pitch range (%lf) incompatible with band gaps (totalling %lf).\n",*pitchrange,gaps);
- return(DATA_ERROR);
- }
- *tessitura = *pitchrange - gaps;
- *tessitura /= dz->param[STRAND_BANDS]; // Tessitura is actual width of bands, after gapping
- if(*tessitura < dz->param[STRAND_MINB]) { // (and before any wavy-banding distortion)
- if(gaps > 0.0) {
- sprintf(errstr,"Pitch range of a band (%lf) incompatible with min bandwidth and band gaps.\n",*tessitura);
- return(DATA_ERROR);
- } else {
- sprintf(errstr,"Pitch range of a band (%lf) incompatible with minimum bandwidth (%lf).\n",*tessitura,dz->param[STRAND_MINB]);
- return(DATA_ERROR);
- }
- }
- // ESTABLISH ARRAYS AS FOLLOWS
- // List of frqs, at specific times, in each strand (dz->itemcnt)
- // Sin table (1)
- // Cos table (1)
- // Pointers into sinetable for each strand (1)
- // Table to store FLOW-TYPES (1)
- universal_arrays = dz->itemcnt + 4;
- // SYNTHESIS ALSO NEEDS....
- // 2nd-derivs of frqdata for each strand, for cubic splining (dz->itemcnt)
- synth_arrays = dz->itemcnt;
- // If 3D, outputs level data
- // List of levels, at specific times, in each strand (dz->itemcnt)
- // 2nd-derivs of leveldata for each strand, for cubic splining (dz->itemcnt)
- rotation_arrays = dz->itemcnt * 2;
-
- if((dz->parray = (double **)malloc((universal_arrays+synth_arrays+rotation_arrays) * sizeof(double *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for data storage.\n");
- return(MEMORY_ERROR);
- }
- // Storage of stream pitch-data
- for(n=0;n<dz->itemcnt;n++) {
- if((dz->parray[n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream-data %d storage and beyond.\n",n+1);
- return(MEMORY_ERROR);
- }
- } // pitches AAAAAAA
- dz->sintable = dz->itemcnt; // +sintab AAAAAAA B
- dz->costable = dz->itemcnt + 1; // +sintab AAAAAAA BC
- dz->sinptrs = dz->itemcnt + 2; // +sinptrs AAAAAAA BCD
- dz->flowdata = dz->itemcnt + 3; // +flowtpye AAAAAAA BCDE
- dz->rotlevel = dz->itemcnt + 4; // +rotlevel AAAAAAA BCDE FFFFFFF
- dz->rotmix = dz->rotlevel; // Used by different modes, (and for info only as variables defined as equivalent)
- dz->derivs = dz->rotlevel + dz->itemcnt; // +levderivs AAAAAAA BCDE FFFFFFF GGGGGGG
- dz->levderivs = dz->rotlevel + dz->itemcnt; // +levderivs AAAAAAA BCDE FFFFFFF GGGGGGG HHHHHHH
- // Establish sinetable: fixed size
- if((dz->parray[dz->sintable] = (double *)malloc((SYNTH_TABSIZE +1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for sine table.\n");
- return(MEMORY_ERROR);
- }
- sintab = dz->parray[dz->sintable];
- for(n=0;n<SYNTH_TABSIZE;n++)
- sintab[n] = sin(PI * 2.0 * ((double)n/(double)SYNTH_TABSIZE));
- sintab[n] = sintab[0]; /* wrap around point */
- // Establish inverted cosine table: fixed size
- if((dz->parray[dz->costable] = (double *)malloc((SYNTH_TABSIZE +1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for cosin table.\n");
- return(MEMORY_ERROR);
- }
- costab = dz->parray[dz->costable];
- for(n=0;n<SYNTH_TABSIZE;n++)
- costab[n] = -cos(PI * 2.0 * ((double)n/(double)SYNTH_TABSIZE));
- costab[n] = costab[0]; /* wrap around point */
- // Establish sine-table pointers: one for each stream
- if((dz->parray[dz->sinptrs] = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for strand sintable pointers.\n");
- return(MEMORY_ERROR);
- }
- // If streams rotate in radial direction, establish arrays to store relative-level-data, +-90 out of phase with pitch motion
- if(dz->iparam[STRAND_3D]) {
- for(n=0;n<dz->itemcnt;n++) {
- if((dz->parray[dz->rotlevel+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing radial motion data %d and beyond.\n",n+1);
- return(MEMORY_ERROR);
- }
- }
- }
- // If sound is to be synthesized
- if(dz->mode == 1) {
- // establish 2nd derivative arrays, for cubic spline interpolation
- for(n=0;n<dz->itemcnt;n++) {
- if((dz->parray[dz->derivs+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing stream-data cubic-spline slope %d and beyond.\n",n+1);
- return(MEMORY_ERROR);
- }
- }
- if(dz->iparam[STRAND_3D]) {
- for(n=0;n<dz->itemcnt;n++) {
- if((dz->parray[dz->levderivs+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing radial motion level cubic-spline slope %d and beyond.\n",n+1);
- return(MEMORY_ERROR);
- }
- }
- }
- // Establish output length in samples
- srate = (double)dz->infile->srate;
- dz->iparam[STRAND_DUR] = (int)round(dz->param[STRAND_DUR] * srate) * dz->infile->channels;
- // Establish end splice length
- endsplice = 50.0 * MS_TO_SECS; // Go for big splice
- if(dz->param[STRAND_DUR] <= endsplice * 2)
- endsplice = min(dz->param[STRAND_DUR]/4.0,5.0 * MS_TO_SECS); // Else go for small splice
- dz->splicesize = (int)floor(endsplice * srate); // Establish size of final splice
- } else {
- if(dz->iparam[STRAND_3D]) {
- // 2nd set of control data files, 180 or 0 out of phase with pitch motion
- for(n=0;n<dz->itemcnt;n++) {
- if((dz->parray[dz->rotmix+n] = (double *)malloc((dz->datasize * 2) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing 2nd radial motion data %d and beyond.\n",n+1);
- return(MEMORY_ERROR);
- }
- }
- }
- }
- // Determine where flow is laminar, or banded, and where it transits between the two
- if((exit_status = establish_flow_types(dz))<0)
- return exit_status;
- // Check turbulence parameter is consistent with physical model
- if((exit_status = check_turbulence_values(isturb,dz))<0)
- return exit_status;
- return(FINISHED);
- }
- /******************************** SYNTHESIS *********************************/
- int synthesis(dataptr dz)
- {
- int exit_status, n, m, cycend = 0, getlevel = 1, bandno, chans = dz->infile->channels;
- int inendsplice, instartsplice;
- int totaloutsamps, sampcnt = 0, startspliceend = dz->splicesize * chans, outsamps_generated, xxtempsize;
- int endsplicestart = dz->iparam[STRAND_DUR] - (dz->splicesize * chans), threadbas;
- double val, maxval = 1.0, srate = (double)dz->infile->srate, time = 0.0, spliceincr, spliceval, normaliser;
- double level, thispitch, thisfrq, pos = -1.0, posstep;
- float *obuf = dz->sampbuf[0];
- double *sinptr = dz->parray[dz->sinptrs], *llev, *rlev;
- // NB This assumes data has been generated, in 1st dz->itemcnt parrays
- dz->tempsize = dz->iparam[STRAND_DUR];
-
- if((llev = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing left levels of stereo output.\n");
- return(MEMORY_ERROR);
- }
- if((rlev = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing right levels of stereo output.\n");
- return(MEMORY_ERROR);
- }
- posstep = 2.0/(double)(dz->iparam[STRAND_BANDS] - 1);
- bandno = 0;
- for(n= 0; n < dz->itemcnt;n++) {
- if((exit_status = spline(n,0,dz))<0) // Establish array of 2nd derivs for cubic spline interp of FRQ values
- return exit_status;
- if(n % dz->iparam[STRAND_THRDS] == 0) { // Establish stere-positioning levels for L+R chann outputs, for each stream
- pancalc(pos,&(llev[bandno]),&(rlev[bandno]));
- pos += posstep;
- bandno++;
- }
- }
- if(dz->iparam[STRAND_3D]) {
- for(n= 0; n< dz->itemcnt;n++) {
- if((exit_status = spline(n,getlevel,dz))<0) // Establish array of 2nd derivs for cubic spline interp of LEVEL values
- return exit_status;
- }
- }
- spliceincr = 1.0/(double)dz->splicesize;
- spliceval = 0.0;
- instartsplice = 1;
- inendsplice = 0;
- totaloutsamps = dz->iparam[STRAND_DUR];
- fprintf(stdout,"INFO: First pass: assessing synthesis level.\n");
- fflush(stdout);
- memset((char *)obuf,0,dz->buflen * sizeof(float));
- for(n=0;n<dz->itemcnt;n++) // Zero sine-table pointers for all streams
- sinptr[n] = 0.0;
- outsamps_generated = 0;
- if(dz->vflag[0]) {
- for(bandno = 0; bandno < dz->iparam[STRAND_BANDS];bandno++) {
- instartsplice = 1;
- inendsplice = 0;
- fprintf(stdout,"INFO: Band %d\n",bandno+1);
- fflush(stdout);
- threadbas = bandno * dz->iparam[STRAND_THRDS];
- outsamps_generated = 0;
- while(outsamps_generated < totaloutsamps) {
- time = (double)outsamps_generated/chans/srate;
- for(m=0,n=threadbas;m<dz->iparam[STRAND_THRDS];n++,m++) {
- thispitch = splint(n,time,0,dz); // Pitch read by cubic-splining between generated values in data output
- thisfrq = miditohz(thispitch);
- val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
- // Use frq to read sinetable, using tabpointer for specific stream
- if(dz->iparam[STRAND_3D]) {
- level = splint(n,time,getlevel,dz); // Read corresponding level
- val *= level;
- }
- obuf[sampcnt] = (float)(obuf[sampcnt] + (val * llev[bandno]));
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * rlev[bandno]));
- }
- if(instartsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval += spliceincr;
- spliceval = min(spliceval,1.0);
- } else if(inendsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval -= spliceincr;
- spliceval = max(spliceval,0.0);
- }
- maxval = max(maxval,fabs(obuf[sampcnt]));
- maxval = max(maxval,fabs(obuf[sampcnt+1]));
- if((sampcnt+=2) >= dz->buflen) {
- dz->process = GREV;
- dz->total_samps_written = outsamps_generated;
- xxtempsize = dz->tempsize;
- dz->tempsize *= dz->iparam[STRAND_BANDS];
- display_virtual_time(dz->total_samps_written,dz);
- dz->tempsize = xxtempsize;
- memset((char *)obuf,0,dz->buflen * sizeof(float));
- sampcnt = 0;
- }
- outsamps_generated += 2;
- if(!inendsplice && (outsamps_generated >= endsplicestart)) {
- inendsplice = 1;
- spliceval = 1.0;
- }
- if(instartsplice && (outsamps_generated >= startspliceend))
- instartsplice = 0;
- }
- dz->process = GREV;
- dz->total_samps_written = outsamps_generated;
- display_virtual_time(dz->total_samps_written,dz);
- dz->process = STRANDS;
- }
- } else {
- while(outsamps_generated < totaloutsamps) {
- time = (double)outsamps_generated/chans/srate;
- for(n=0;n<dz->itemcnt;n++) {
- bandno = n/dz->iparam[STRAND_THRDS];
- thispitch = splint(n,time,0,dz); // Pitch read by cubic-splining between generated values in data output
- thisfrq = miditohz(thispitch);
- val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
- // Use frq to read sinetable, using tabpointer for specific stream
- if(dz->iparam[STRAND_3D]) {
- level = splint(n,time,getlevel,dz); // Read corresponding level
- val *= level;
- }
- obuf[sampcnt] = (float)(obuf[sampcnt] + (val * llev[bandno]));
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * rlev[bandno]));
- }
- if(instartsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval += spliceincr;
- spliceval = min(spliceval,1.0);
- } else if(inendsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval -= spliceincr;
- spliceval = max(spliceval,0.0);
- }
- maxval = max(maxval,fabs(obuf[sampcnt]));
- maxval = max(maxval,fabs(obuf[sampcnt+1]));
- if((sampcnt+=2) >= dz->buflen) {
- dz->process = GREV;
- dz->total_samps_written = outsamps_generated;
- display_virtual_time(dz->total_samps_written,dz);
- dz->process = STRANDS;
- memset((char *)obuf,0,dz->buflen * sizeof(float));
- sampcnt = 0;
- }
- outsamps_generated += 2;
- if(!inendsplice && (outsamps_generated >= endsplicestart)) {
- inendsplice = 1;
- spliceval = 1.0;
- }
- if(instartsplice && (outsamps_generated >= startspliceend))
- instartsplice = 0;
- }
- dz->process = GREV;
- dz->total_samps_written = outsamps_generated;
- display_virtual_time(dz->total_samps_written,dz);
- dz->process = STRANDS;
- }
- normaliser = 0.85/maxval;
- time = 0.0;
- spliceval = 0.0;
- instartsplice = 1;
- inendsplice = 0;
- dz->total_samps_written = 0;
- outsamps_generated = 0;
- sampcnt = 0;
- for(n=0;n<dz->itemcnt;n++) // Zero sine-table pointers for all streams
- sinptr[n] = 0.0;
- fprintf(stdout,"INFO: Second pass: synthesis.\n");
- fflush(stdout);
- memset((char *)obuf,0,dz->buflen * sizeof(float));
- if(dz->vflag[0]) {
- for(bandno = 0; bandno < dz->iparam[STRAND_BANDS];bandno++) {
- instartsplice = 1;
- inendsplice = 0;
- fprintf(stdout,"INFO: Band %d\n",bandno+1);
- fflush(stdout);
- threadbas = bandno * dz->iparam[STRAND_THRDS];
- outsamps_generated = 0;
- while(outsamps_generated < totaloutsamps) {
- time = (double)outsamps_generated/chans/srate;
- for(m=0,n=threadbas;m<dz->iparam[STRAND_THRDS];n++,m++) {
- thispitch = splint(n,time,0,dz); // Frq read by cubic-splining between generated values in data output
- thisfrq = miditohz(thispitch);
- val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
- // Use frq to read sinetable, using tabpointer for specific stream
- if(dz->iparam[STRAND_3D]) {
- level = splint(n,time,getlevel,dz); // Read corresponding level
- val *= level;
- }
- obuf[sampcnt] = (float)(obuf[sampcnt] + (val * rlev[bandno]));
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * llev[bandno]));
- if(instartsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval += spliceincr;
- spliceval = min(spliceval,1.0);
- } else if(inendsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval -= spliceincr;
- spliceval = max(spliceval,0.0);
- }
- }
- outsamps_generated += 2;
- if(!inendsplice && (outsamps_generated >= endsplicestart)) {
- inendsplice = 1;
- spliceval = 1.0;
- }
- if(instartsplice && (outsamps_generated >= startspliceend))
- instartsplice = 0;
- if((sampcnt+=2) >= dz->buflen) {
- dz->process = GREV;
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- dz->process = STRANDS;
- sampcnt = 0;
- memset((char *)obuf,0,dz->buflen * sizeof(float));
- }
- }
- }
- } else {
- while(outsamps_generated < totaloutsamps) {
- time = (double)outsamps_generated/chans/srate;
- for(n=0;n<dz->itemcnt;n++) {
- bandno = n/dz->iparam[STRAND_THRDS];
- thispitch = splint(n,time,0,dz); // Frq read by cubic-splining between generated values in data output
- thisfrq = miditohz(thispitch);
- val = sinread(0,&(sinptr[n]),thisfrq,&cycend,dz->scalefact,dz);
- // Use frq to read sinetable, using tabpointer for specific stream
- if(dz->iparam[STRAND_3D]) {
- level = splint(n,time,getlevel,dz); // Read corresponding level
- val *= level;
- }
- obuf[sampcnt] = (float)(obuf[sampcnt] + (val * rlev[bandno]));
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] + (val * llev[bandno]));
- }
- obuf[sampcnt] = (float)(obuf[sampcnt] * normaliser);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * normaliser);
- if(instartsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval += spliceincr;
- spliceval = min(spliceval,1.0);
- } else if(inendsplice) {
- obuf[sampcnt] = (float)(obuf[sampcnt] * spliceval);
- obuf[sampcnt+1] = (float)(obuf[sampcnt+1] * spliceval);
- spliceval -= spliceincr;
- spliceval = max(spliceval,0.0);
- }
- outsamps_generated += 2;
- if(!inendsplice && (outsamps_generated >= endsplicestart)) {
- inendsplice = 1;
- spliceval = 1.0;
- }
- if(instartsplice && (outsamps_generated >= startspliceend))
- instartsplice = 0;
- if((sampcnt+=2) >= dz->buflen) {
- dz->process = GREV;
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- dz->process = STRANDS;
- sampcnt = 0;
- memset((char *)obuf,0,dz->buflen * sizeof(float));
- }
- }
- }
- if(sampcnt) {
- dz->process = GREV;
- if((exit_status = write_samps(obuf,sampcnt,dz))<0)
- return(exit_status);
- dz->process = STRANDS;
- }
- return FINISHED;
- }
- /**************************** CREATE_STRANDS_SNDBUFS ****************************/
- int create_strands_sndbufs(dataptr dz)
- {
- int n;
- int bigbufsize;
- int framesize;
- framesize = F_SECSIZE;
- dz->bufcnt = 1;
- if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
- return(MEMORY_ERROR);
- }
- if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
- return(MEMORY_ERROR);
- }
- bigbufsize = (int)Malloc(-1);
- bigbufsize /= dz->bufcnt;
- if(bigbufsize <=0)
- bigbufsize = framesize * sizeof(float);
- dz->buflen = bigbufsize / sizeof(float);
- dz->buflen = (dz->buflen / framesize) * framesize;
- bigbufsize = dz->buflen * sizeof(float);
- if((dz->bigbuf = (float *)malloc(bigbufsize * dz->bufcnt)) == NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
- return(PROGRAM_ERROR);
- }
- for(n=0;n<dz->bufcnt;n++)
- dz->sbufptr[n] = dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
- dz->sampbuf[n] = dz->bigbuf + (dz->buflen * n);
- return(FINISHED);
- }
- /****************************** GET_THE_MODE_FROM_CMDLINE *********************************/
- int get_the_mode_from_cmdline(char *str,dataptr dz)
- {
- char temp[200], *p;
- if(sscanf(str,"%s",temp)!=1) {
- fprintf(stderr,"Cannot read mode of program.\n");
- return(USAGE_ONLY);
- }
- p = temp + strlen(temp) - 1;
- while(p >= temp) {
- if(!isdigit(*p)) {
- fprintf(stderr,"Invalid mode of program entered.\n");
- return(USAGE_ONLY);
- }
- p--;
- }
- if(sscanf(str,"%d",&dz->mode)!=1) {
- fprintf(stderr,"Cannot read mode of program.\n");
- return(USAGE_ONLY);
- }
- if(dz->mode <= 0 || dz->mode > dz->maxmode) {
- fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
- return(USAGE_ONLY);
- }
- dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
- return(FINISHED);
- }
- /**************************** SINREAD *************************/
-
- double sinread(int iscos,double *tabpos,double frq,int *cycend,double scaling,dataptr dz)
- {
- double tabincr, val, valdiff, timefrac;
- int lopos, hipos;
- double *sintab;
- if(iscos)
- sintab = dz->parray[dz->costable];
- else
- sintab = dz->parray[dz->sintable];
- *cycend = 0;
- lopos = (int)floor(*tabpos);
- hipos = (int)ceil(*tabpos);
- timefrac = *tabpos - (double)lopos;
- val = sintab[lopos];
- valdiff = sintab[hipos] - val;
- val += valdiff * timefrac;
- tabincr = frq * scaling;
- *tabpos += tabincr;
- if(*tabpos >= SYNTH_TABSIZE) {
- *cycend = 1;
- *tabpos -= SYNTH_TABSIZE;
- }
- return val;
- }
- /*************************************** SPLINE *******************************
- *
- * Establish 2nd dervatives table for cubic spline calculations.
- */
- int spline(int streamno,int islevel,dataptr dz)
- {
- double firstderivatzero = 0.0, firstderivatend = 0.0, qn, un, val1, val2; // firstderiveatend is a guess
- double *datatab, *secondderiv, *u;
- int arraysize = dz->datasize;
- int n, t, v, tt, vv, k;
- double thistimestep, thisfrqstep, nexttimestep,nextfrqstep,bigtimestep, lasttime, lastval,sig,p;
- if((u = (double *)malloc(arraysize * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for calculating spline derivatives.\n");
- return(MEMORY_ERROR);
- }
- if(islevel) {
- datatab = dz->parray[dz->rotlevel+streamno]; // The stored level data already calcd for stream "streamno"
- secondderiv = dz->parray[dz->levderivs+streamno];
- } else {
- datatab = dz->parray[streamno]; // The stored frq data already calcd for stream "streamno"
- secondderiv = dz->parray[dz->derivs+streamno];
- }
- secondderiv[0] = -0.5;
- thistimestep = datatab[2] - datatab[0];
- thisfrqstep = datatab[3] - datatab[1];
- val1 = 3.0/thistimestep;
- val2 = (thisfrqstep/thistimestep) - firstderivatzero;
- u[0] = val1 * val2;
- lasttime = datatab[0];
- lastval = datatab[1];
- 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
- thisfrqstep = datatab[v] - lastval; // tt indexes NEXT time, vv indexes NEXT value
- nextfrqstep = datatab[vv] - datatab[v];
- thistimestep = datatab[t] - lasttime;
- nexttimestep = datatab[tt] - datatab[t];
- bigtimestep = datatab[tt] - lasttime;
- sig = thistimestep/bigtimestep;
- p = (sig * secondderiv[n-1]) + 2.0;
- secondderiv[n] = (sig - 1.0)/p;
- u[n] = (nextfrqstep/nexttimestep) - (thisfrqstep/thistimestep);
- u[n] = (6.0 * u[n])/bigtimestep;
- u[n] -= sig * u[n-1];
- u[n] /= p;
- lasttime = datatab[t];
- lastval = datatab[v];
- }
- qn = 0.5;
- thisfrqstep = datatab[v] - lastval;
- thistimestep = datatab[t] - lasttime;
- val1 = 3.0/thistimestep;
- val2 = firstderivatend - (thisfrqstep/thistimestep);
- un = val1 * val2;
- val1 = un - (qn * u[n-1]);
- val2 = (qn * secondderiv[n-1]) + 1.0;
- secondderiv[n] = val1/val2;
- for(k = n-1;k >= 0;k--)
- secondderiv[k] = (secondderiv[k] * secondderiv[k+1]) + u[k];
- return FINISHED;
- }
- /*************************************** SPLINE_LEVEL *******************************
- *
- * Establish 2nd dervatives table for cubic spline calculations.
- */
- int spline_level(int streamno,dataptr dz)
- {
- double firstderivatzero = 0.0, firstderivatend = 0.0, qn, un, val1, val2; // firstderiveatend is a guess
- double *levtab = dz->parray[dz->rotlevel + streamno]; // The stored frq data already calcd for stream "streamno"
- int arraysize = dz->datasize;
- double *secondderiv = dz->parray[dz->levderivs + streamno], *u;
- int n, t, v, tt, vv, k;
- double thistimestep, thisfrqstep, nexttimestep,nextfrqstep,bigtimestep, lasttime, lastval,sig,p;
- if((u = (double *)malloc(arraysize * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for calculating spline derivatives.\n");
- return(MEMORY_ERROR);
- }
- secondderiv[0] = -0.5;
- thistimestep = levtab[2] - levtab[0];
- thisfrqstep = levtab[3] - levtab[1];
- val1 = 3.0/thistimestep;
- val2 = (thisfrqstep/thistimestep) - firstderivatzero;
- u[0] = val1 * val2;
- lasttime = levtab[0];
- lastval = levtab[1];
- 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
- thisfrqstep = levtab[v] - lastval; // tt indexes NEXT time, vv indexes NEXT value
- nextfrqstep = levtab[vv] - levtab[v];
- thistimestep = levtab[t] - lasttime;
- nexttimestep = levtab[tt] - levtab[t];
- bigtimestep = levtab[tt] - lasttime;
- sig = thistimestep/bigtimestep;
- p = (sig * secondderiv[n-1]) + 2.0;
- secondderiv[n] = (sig - 1.0)/p;
- u[n] = (nextfrqstep/nexttimestep) - (thisfrqstep/thistimestep);
- u[n] = (6.0 * u[n])/bigtimestep;
- u[n] -= sig * u[n-1];
- u[n] /= p;
- lasttime = levtab[t];
- lastval = levtab[v];
- }
- qn = 0.5;
- thisfrqstep = levtab[v] - lastval;
- thistimestep = levtab[t] - lasttime;
- val1 = 3.0/thistimestep;
- val2 = firstderivatend - (thisfrqstep/thistimestep);
- un = val1 * val2;
- val1 = un - (qn * u[n-1]);
- val2 = (qn * secondderiv[n-1]) + 1.0;
- secondderiv[n] = val1/val2;
- for(k = n-1;k >= 0;k--)
- secondderiv[k] = (secondderiv[k] * secondderiv[k+1]) + u[k];
- return FINISHED;
- }
- /*************************************** SPLINT *******************************
- *
- * Do cubic spline, using 2nd dervatives table.
- */
- double splint(int streamno,double time,int islevel,dataptr dz)
- {
- double *datatab, *secondderiv;
- int arraysize = dz->datasize;
- int hitim, lotim, hival, loval; // time and value indeces into brkpoint array
- int hideriv, loderiv; // upper and lower indices into 2nd derivatives array
- double timestep, hitimefrac, lotimefrac, val1, val2, val3;
- if(islevel) {
- datatab = dz->parray[dz->rotlevel+streamno];
- secondderiv = dz->parray[dz->levderivs+streamno];
- } else {
- datatab = dz->parray[streamno];
- secondderiv = dz->parray[dz->derivs+streamno];
- }
- if(time <= datatab[0])
- return datatab[1];
- hideriv = 0;
- hitim = 0;
- while(time > datatab[hitim]) {
- hitim+=2;
- hideriv++;
- if(hideriv >= arraysize)
- return datatab[(arraysize * 2)-1]; // last value in table
- }
- loderiv = hideriv - 1;
- lotim = hitim - 2;
- loval = lotim+1;
- hival = hitim+1;
- timestep = datatab[hitim] - datatab[lotim];
- hitimefrac = (datatab[hitim] - time)/timestep;
- lotimefrac = (time - datatab[lotim])/timestep;
-
- val1 = hitimefrac * datatab[loval];
- val1 += lotimefrac * datatab[hival];
- val2 = (hitimefrac * hitimefrac * hitimefrac) - hitimefrac;
- val2 *= secondderiv[loderiv];
- val3 = (lotimefrac * lotimefrac * lotimefrac) - lotimefrac;
- val3 *= secondderiv[hideriv];
- val2 += val3;
- val2 *= (timestep * timestep)/6.0;
- val1 += val2;
- return val1;
- }
- /****************************** STRANDS ***********************************/
- int strands(double pitchrange,double band_separation,double tessitura,int isturb,dataptr dz)
- {
- int exit_status, n, t, flow_type, istwist = 0, *permlocal = NULL, *permglobal = NULL, rotup = dz->iparam[STRAND_3D], thth, threadscnt;
- int outcnt = 0, entrycnt;
- double time = 0.0;
- double *lastcycendtime, *bandtwist, *tabpos, *bandtopmean, *bandtop, *bandbot, *phasoffset, *flow;
- double *wtabpos, *wavyfrq, *lampitch, *turbpset = NULL, *localturbpitch = NULL, *globalturbpitch = NULL;
- double bandhalfgap, frqrange, frqmin, speedscat, squeeze, bandwidth, halfbandwidth, bandcentre, lasttabpos, thistabpos, thistabpos2, sinval;
- int *cycend, *wcycend, dummycycend, piover2phaseshift, piphaseshift, phasdist, th, bandno, threadbas, newcycle, iswavy, lastiswavy, *threadlens = NULL;
- double lamstep, halflamstep, pitchwander, level, twistreffrq = 0.0, gturb;
- double transittime = 0.0, transitfrac, laminarpitch, thisthreadcentre, thishalfbandwidth, thisturb;
- double upbandwidth, dnbandwidth, upbandlim, dnbandlim, xs, lamlevel, pitch, transitstart, vamp, thisbandbot;
- if(dz->mode == 2)
- threadlens = dz->iparray[0]; // Time of end of previous twist-cycle
- // Used when scattering stream-times within cycle
- if((lastcycendtime = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing endtime of cycle in each band.\n");
- return(MEMORY_ERROR);
- } // Flag that band's twist cycle has been completed
- if((cycend = (int *)malloc(dz->iparam[STRAND_BANDS] * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing twist cycle completion flags.\n");
- return(MEMORY_ERROR);
- }
- for(bandno = 0;bandno < dz->iparam[STRAND_BANDS];bandno++) { // Initialise all cycle-end flags to 0
- lastcycendtime[bandno] = 0.0;
- cycend[bandno] = 0;
- } // frq of each laminar thread
- if((lampitch = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing frqs of laminar threads.\n");
- return(MEMORY_ERROR);
- } // twisting rate of each band
- if((bandtwist = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing twist rate of each band.\n");
- return(MEMORY_ERROR);
- } // Sintable read-position for each thread
- if((tabpos = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing sinetable read-position in each band.\n");
- return(MEMORY_ERROR);
- } // Sintable read-position for wavy band-boundaries
- if((wtabpos = (double *)malloc((dz->iparam[STRAND_BANDS] - 1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing Sintable read-position for wavy band-boundaries.\n");
- return(MEMORY_ERROR);
- } // wavy band-boundaries oscillation-frequency
- if((wcycend = (int*)malloc((dz->iparam[STRAND_BANDS] - 1) * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing Sintable cycle end markers for wavy band-boundaries.\n");
- return(MEMORY_ERROR);
- } // wavy band-boundaries oscillation-frequency
- if((wavyfrq = (double *)malloc((dz->iparam[STRAND_BANDS] - 1) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing wavy band-boundaries oscillation-frequency.\n");
- return(MEMORY_ERROR);
- } // upper boundary pitches of each band (ignoring any gapping)
- if((bandtopmean = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing upper boundary pitches of each band.\n");
- return(MEMORY_ERROR);
- } // lower boundary pitches of each band (ignoring any gapping)
- if((bandtop = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing lower boundary pitches of each band.\n");
- return(MEMORY_ERROR);
- } // Current bottom pitch of each band
- if((bandbot = (double *)malloc(dz->iparam[STRAND_BANDS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing Current bottom pitch of each band.\n");
- return(MEMORY_ERROR);
- } // Phase offset of pointers defining streams within a band
- if((phasoffset = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing Phase offset of pointers defining streams within a band.\n");
- return(MEMORY_ERROR);
- }
- if(isturb) {
- if((turbpset = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing pre-assigned turbulence pitches.\n");
- return(MEMORY_ERROR);
- }
- if((localturbpitch = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing local turbulence pitches.\n");
- return(MEMORY_ERROR);
- }
- if((globalturbpitch = (double *)malloc(dz->itemcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing global turbulence pitches.\n");
- return(MEMORY_ERROR);
- }
- if((permlocal = (int *)malloc(dz->itemcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing local turbulence pitches.\n");
- return(MEMORY_ERROR);
- }
- if((permglobal = (int *)malloc(dz->itemcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing global turbulence pitches.\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n < dz->itemcnt;n++) {
- permlocal[n] = n;
- permglobal[n] = n;
- }
- }
- flow = dz->parray[dz->flowdata];
- // Establish phase-offset for 3-d motion : level mix is PI/2 out of phase with pitch-reading.
- piover2phaseshift = (int)round((double)SYNTH_TABSIZE/4.0);
- piphaseshift = (int)round((double)SYNTH_TABSIZE/2.0);
- thth = 0;
- if(dz->mode == 2) {
- // Establish phase-offset of streams within bands
- for(n = 0;n < dz->iparam[STRAND_BANDS];n++) {
- threadscnt = threadlens[n];
- phasdist = (int)round((double)SYNTH_TABSIZE/(double)threadscnt);
- for(th = 0;th < threadscnt;th++) {
- phasoffset[thth] = th * phasdist;
- thth++;
- }
- }
- } else {
- // Establish phase-offset of streams within bands
- phasdist = (int)round((double)SYNTH_TABSIZE/(double)dz->iparam[STRAND_THRDS]);
- for(n = 0;n < dz->iparam[STRAND_BANDS];n++) {
- for(th = 0;th < dz->iparam[STRAND_THRDS];th++) {
- phasoffset[thth] = th * phasdist;
- thth++;
- }
- }
- }
- // Preset phase-of sinetable read for threads in each band
- for(th = 0;th < dz->itemcnt;th++)
- tabpos[th] = phasoffset[th];
- // Get initial value of all time-varying variables
- time = 0;
- if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
- return exit_status;
- // Intialise band boundaries (before any gapping)
- bandhalfgap = dz->param[STRAND_GAP]/2.0;
- bandtopmean[0] = dz->param[STRAND_BOT] + band_separation; // bandtopmean is generally in the gap between bands,
- for(bandno=1; bandno < dz->iparam[STRAND_BANDS]-1;bandno++) // or at the top and bottom limits of entire pitchrange
- bandtopmean[bandno] = bandtopmean[bandno-1] + band_separation;
- bandtopmean[bandno] = dz->param[STRAND_TOP]; // bandtopmean is generally in the gap between bands,
- // Initialise actual band limits (after gapping)
-
- bandbot[0] = dz->param[STRAND_BOT];
- for(bandno=1; bandno < dz->iparam[STRAND_BANDS];bandno++)
- bandbot[bandno] = bandtopmean[bandno-1] + bandhalfgap;
- for(bandno=0; bandno < dz->iparam[STRAND_BANDS] - 1;bandno++)
- bandtop[bandno] = bandtopmean[bandno] - bandhalfgap;
- bandtop[bandno] = dz->param[STRAND_TOP];
- // Preset all wavyfrequences, for waviness of band boundaries
- lastiswavy = 0;
- // Initialise all frqs for any possible laminar flow
- lamstep = pitchrange/(double)(dz->itemcnt - 1);
- halflamstep = lamstep/2.0;
- lampitch[0] = dz->param[STRAND_BOT];
- for(th = 1;th < dz->itemcnt-1; th++)
- lampitch[th] = lampitch[th-1] + lamstep;
- lampitch[th] = dz->param[STRAND_TOP];
- // Initialise all frqs for any possible twisted flow
- for(n=0,t=0;n < dz->flowcnt;n++,t+=4) {
- flow_type = (int)round(flow[t+1]);
- if(flow_type != LAMINAR) { // TOTWIST,and FROMTWIST (as well as TWISTED) both need bandtwist-frq values etc
- transitstart = flow[t];
- twistreffrq = flow[t+2];
- transittime = flow[t+3];
- istwist = 1;
- break;
- }
- }
- if(istwist) {
- for(bandno = 0;bandno < dz->iparam[STRAND_BANDS];bandno++) {
- bandtwist[bandno] = twistreffrq; // get twist-freq of band read from start of true twist
- if(dz->param[STRAND_RAND] > 0.0) { // If randomised (from one band to another): generate random scatter
- speedscat = drand48() * dz->param[STRAND_RAND];
- speedscat += 1.0; // Allowing frq-scatter in range *1 to (max)*2
- if(drand48() < 0.5) // and, at random, select N or 1/N (maximal range *1/2 to *2)
- speedscat = 1.0/speedscat;
- bandtwist[bandno] *= speedscat; // and set randomised value as true twist-frequency of band
- }
- }
- }
- flow_type = get_flow_type(0.0,&transitstart,&twistreffrq,&transittime,dz);
- while(outcnt < dz->datasize) {
- if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
- return exit_status;
- iswavy = 0;
- if(dz->param[STRAND_VAMP] > 0.0 && (dz->param[STRAND_VMIN] > 0.0 || dz->param[STRAND_VMAX] > 0.0))
- iswavy = 1;
- if(!lastiswavy && iswavy) { // When waviness starts, set up cycle reading in sintable
- frqrange = fabs(dz->param[STRAND_VMAX] - dz->param[STRAND_VMIN]);
- frqmin = min(dz->param[STRAND_VMAX],dz->param[STRAND_VMIN]);
- for(bandno = 0; bandno < dz->iparam[STRAND_BANDS] - 1; bandno++) {
- wavyfrq[bandno] = drand48() * frqrange;
- wavyfrq[bandno] += frqmin;
- wcycend[bandno] = 0;
- }
- }
- lastiswavy = iswavy;
- switch(flow_type) {
- case(LAMINAR):
- for(th = 0;th < dz->itemcnt;th++) {
- pitch = lampitch[th];
- pitchwander = dz->param[STRAND_RAND] * halflamstep;
- if(th == 0)
- pitchwander *= drand48();
- else if(th == dz->itemcnt - 1)
- pitchwander *= -drand48();
- else
- pitchwander *= (drand48() * 2.0) - 1.0;
- pitch += pitchwander;
- entrycnt = outcnt * 2; // Save pitch vals generated
- dz->parray[th][entrycnt++] = time;
- dz->parray[th][entrycnt++] = pitch;
- if(dz->iparam[STRAND_3D]) {
- level = dz->param[STRAND_SCAT] * drand48();
- level = 1.0 - level;
- entrycnt = outcnt * 2; // Save level vals generated
- dz->parray[dz->rotlevel+th][entrycnt++] = time;
- dz->parray[dz->rotlevel+th][entrycnt++] = level;
- entrycnt = outcnt * 2; // Dummy values for reverb-etc mix
- dz->parray[dz->rotmix+th][entrycnt++] = time;
- dz->parray[dz->rotmix+th][entrycnt++] = 0.0;
- }
- }
- break;
- case(TWISTED):
- rotup = dz->iparam[STRAND_3D];
-
- // IF TURBULENCE IS (APPROACHING) GLOBAL: calculate turbulence pitches over entire range, across all bands
- if(dz->param[STRAND_TURB] >= 1.0)
- assign_turbulence_pitches(dz->itemcnt,dz->param[STRAND_BOT],pitchrange,permglobal,turbpset,globalturbpitch);
- // for each band in turn
- threadbas = 0;
- for(bandno = 0;bandno < dz->iparam[STRAND_BANDS]; bandno++) {
- if(dz->mode == 2)
- threadscnt = threadlens[bandno];
- else {
- threadscnt = dz->iparam[STRAND_THRDS];
- threadbas = bandno * dz->iparam[STRAND_THRDS]; // Get index of lowest thread in band
- }
- // IF TURBULENCE IS IN-BAND OR GLOBAL: Calculate turbulence pitches WITHIN band
- if(dz->param[STRAND_TURB] > 0.0) {
- if(bandno == 0)
- thisbandbot = dz->param[STRAND_BOT];
- else
- thisbandbot = bandtopmean[bandno-1];
- assign_turbulence_pitches(threadscnt,thisbandbot,tessitura,permlocal + threadbas,turbpset,localturbpitch);
- }
-
- // If at end of a twist cylce for the band, scatter previous cycle times, and recalculate twist frequency
- newcycle = 0;
- if(cycend[bandno]) { // If band twist-cycle reaches sintab end
- if(dz->param[STRAND_SCAT] > 0.0) // Scatter data in this band, over last cycle
- scatter_streamdata_in_last_cycle(time,bandno,threadscnt,threadbas,outcnt,lastcycendtime[bandno],dz);
- lastcycendtime[bandno] = time; // Note start of next cycle
- cycend[bandno] = 0; // Unmark "end of cycle"
- newcycle = 1;
- bandtwist[bandno] = dz->param[STRAND_TWIST]; // get twist-freq of band read from input data
- if(dz->param[STRAND_RAND] > 0.0) { // If randomised (from one band to another): generate random scatter
- speedscat = drand48() * dz->param[STRAND_RAND];
- speedscat += 1.0; // Allowing frq-scatter in range *1 to (max)*2
- if(drand48() < 0.5) // and, at random, select N or 1/N (maximal range *1/2 to *2)
- speedscat = 1.0/speedscat;
- bandtwist[bandno] *= speedscat; // and set randomised value as true twist-frequency of band
- }
- }
- if(bandno < dz->iparam[STRAND_BANDS] - 1) {
- // Use warp factors to get any wavy-variation of top boundary for current band (except for top of top band which is fixed)
- if(iswavy && dz->param[STRAND_TURB] < 1.0) { // If Turbulence >= 1, no longer ness to calc wavy-boundaries
- vamp = dz->param[STRAND_VAMP]; // Amplitude of waviness decreases as turbulence increases (0->1)
- if(dz->param[STRAND_TURB] > 0.0) // The factor (1 - turbulence), with values (1->0) is used.
- vamp *= pow((1 - dz->param[STRAND_TURB]),TURBFLATTEN); // TURBFLATTEN makes curve dip towards zero more quickly at start.
- bandtop[bandno] = wavy(bandno,bandtopmean[bandno],tessitura,vamp,&(wavyfrq[bandno]),&(wtabpos[bandno]),&(wcycend[bandno]),dz->scaler,dz);
- // Use halfgap to force band separation
- bandtop[bandno] -= bandhalfgap;
- } else
- bandtop[bandno] = bandtopmean[bandno] - bandhalfgap;
- } // Use previously calcd value of top of next lowest band,
- if(bandno > 0) // to find bottom boundary of current band.
- bandbot[bandno] = bandtop[bandno - 1] + dz->param[STRAND_GAP]; // using gap to force band separation
- // Use band minimum width to modify values, if ness
- bandwidth = bandtop[bandno] - bandbot[bandno];
- if((squeeze = dz->param[STRAND_MINB] - bandwidth) > 0) {
- bandtop[bandno] += squeeze;
- bandwidth = bandtop[bandno] - bandbot[bandno];
- }
- halfbandwidth = bandwidth/2.0;
- bandcentre = bandbot[bandno] + halfbandwidth;
- // SAFETY: recalibrate the phase-offsets for the strans
- if(newcycle) {
- for(th=1;th<threadscnt;th++) {
- tabpos[threadbas + th] = tabpos[threadbas] + phasoffset[threadbas + th];
- if(tabpos[threadbas + th] >= SYNTH_TABSIZE)
- tabpos[threadbas + th] -= (double)SYNTH_TABSIZE;
- }
- newcycle = 0;
- }
- thisturb = dz->param[STRAND_TURB];
- for(th=0;th<threadscnt;th++) {
- lasttabpos = tabpos[threadbas+th]; // Remember current table location
- if(thisturb == 2.0) // TOTAL GLOBAL TURBULENCE
- pitch = globalturbpitch[threadbas+th]; // use global turbulence pitch
- else if(thisturb >= 1.0) // TOTAL INBAND TURBULENCE or beyond
- pitch = localturbpitch[threadbas+th]; // use in-band turbulent pitch
- else { // turb < 1.0 // ELSE: (some degree of) TWISTING : Read sintable at correct location
- if(th==0) // ONLY lowest thread used to count cycles
- sinval = sinread(1,&(tabpos[threadbas]),bandtwist[bandno],&(cycend[bandno]),dz->scaler,dz);
- else
- sinval = sinread(1,&(tabpos[threadbas+th]),bandtwist[bandno],&dummycycend,dz->scaler,dz);
- pitch = sinval * halfbandwidth; // Expand -1-to +1 range to fit into bandwidth
- pitch += bandcentre;
- }
- if(thisturb > 0.0) { // If turbulent
- if(thisturb < 1.0) // MOVING TOWARDS INBAND TURBULENCE :
- // pitch is from sinval : interpolate towards in-band turbulent pitch
- pitch = ((1.0 - thisturb) * pitch) + (thisturb * localturbpitch[threadbas+th]);
- else if(thisturb < 2.0) { // thisturb >= 1.0
- gturb = thisturb - 1.0; // MOVING TOWARDS GLOBAL TURBULENCE :
- // pitch is from localturbpitch : interpolate towards global turbulent pitch
- pitch = ((1.0 - gturb) * pitch) + (gturb * globalturbpitch[threadbas+th]);
- }
- }
- entrycnt = outcnt * 2; // Save pitch vals generated
- dz->parray[threadbas + th][entrycnt++] = time;
- dz->parray[threadbas + th][entrycnt++] = pitch;
- if(rotup) { // If band is to turn in radial direction
-
- switch(rotup) { // generate phase-shifted data for mixing filtered copy
- case(1):
- thistabpos = lasttabpos + piover2phaseshift; // Rotating UP at the front
- while(thistabpos >= SYNTH_TABSIZE)
- thistabpos -= (double)SYNTH_TABSIZE;
- thistabpos2 = lasttabpos + piphaseshift;
- while(thistabpos2 >= SYNTH_TABSIZE)
- thistabpos2 -= (double)SYNTH_TABSIZE;
- break;
- case(-1): // Rotating DOWN at the front
- thistabpos = lasttabpos - piover2phaseshift;
- while(thistabpos < 0)
- thistabpos += (double)SYNTH_TABSIZE;
- thistabpos2 = lasttabpos;
- break;
- }
- sinval = sinread(1,&thistabpos,bandtwist[bandno],&dummycycend,dz->scaler,dz);
- level = sinval + 1.0; // Scale into 0 to 1 range
- level /= 2.0;
- if(dz->param[STRAND_TURB] > 0.0)
- level = turblevel(dz->param[STRAND_TURB],level,dz);
- entrycnt = outcnt * 2; // Save mixdata values
- dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = time;
- dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = level;
- sinval = sinread(1,&thistabpos2,bandtwist[bandno],&dummycycend,dz->scaler,dz);
- level = sinval + 1.0; // Scale into 0 to 1 range
- level /= 2.0;
- if(dz->param[STRAND_TURB] > 0.0) // THIS IS ILLOGICAL, BUT perhaps OK for turbulent flow!!
- level = turblevel(dz->param[STRAND_TURB],level,dz);
- entrycnt = outcnt * 2; // Save mixdata values
- dz->parray[dz->rotmix + threadbas + th][entrycnt++] = time;
- dz->parray[dz->rotmix + threadbas + th][entrycnt++] = level;
- }
- }
- rotup = -rotup; // If rotating, alternate bands rotate in opposite directions
- if(dz->mode == 2)
- threadbas += threadscnt;
- }
- break;
- case(TOTWIST):
- case(FROMTWIST):
- rotup = dz->iparam[STRAND_3D];
-
- transitfrac = (time - transitstart)/transittime; // Fractional position in transit to full twisting
- // THE FOLLOWING CODE IS DONE AS IF WE'RE ALREADY IN A FULL TWIST
-
- threadbas = 0;
- for(bandno = 0;bandno < dz->iparam[STRAND_BANDS]; bandno++) {
-
- if(dz->mode == 2)
- threadscnt = threadlens[bandno];
- else {
- threadscnt = dz->iparam[STRAND_THRDS];
- threadbas = bandno * dz->iparam[STRAND_THRDS];
- }
- newcycle = 0;
- if(cycend[bandno]) {
- if(dz->param[STRAND_SCAT] > 0.0)
- scatter_streamdata_in_last_cycle(time,bandno,threadscnt,threadbas,outcnt,lastcycendtime[bandno],dz);
- lastcycendtime[bandno] = time;
- cycend[bandno] = 0;
- newcycle = 1;
- bandtwist[bandno] = twistreffrq;
- if(dz->param[STRAND_RAND] > 0.0) {
- speedscat = drand48() * dz->param[STRAND_RAND];
- speedscat += 1.0;
- if(drand48() < 0.5)
- speedscat = 1.0/speedscat;
- bandtwist[bandno] *= speedscat;
- }
- }
- // WAVY BAND BOUNDARIES NOT PERMITTED IN TRANSITION TO TWIST
- if(bandno < dz->iparam[STRAND_BANDS] - 1)
- bandtop[bandno] = bandtopmean[bandno] - bandhalfgap;
- if(bandno > 0)
- bandbot[bandno] = bandtop[bandno - 1] + bandhalfgap;
- bandwidth = bandtop[bandno] - bandbot[bandno];
- if((squeeze = dz->param[STRAND_MINB] - bandwidth) > 0) {
- bandtop[bandno] += squeeze;
- bandwidth = bandtop[bandno] - bandbot[bandno];
- }
- halfbandwidth = bandwidth/2.0;
- bandcentre = bandbot[bandno] + halfbandwidth;
- if(newcycle) {
- for(th=1;th<threadscnt;th++) {
- tabpos[threadbas + th] = tabpos[threadbas] + phasoffset[threadbas + th];
- if(tabpos[threadbas + th] >= SYNTH_TABSIZE)
- tabpos[threadbas + th] -= (double)SYNTH_TABSIZE;
- }
- }
- // WE NOW INTEGRATE THE LAMINAR AND THE TWIST INFORMATION
-
- if(flow_type == TOTWIST)
- bandwidth *= transitfrac; // Twist bandwidth increases from zero to full as we do transit to twist
- else
- bandwidth *= (1.0 - transitfrac); // Twist bandwidth decreases from full to zero as we do transit from twist
- // CALCUALTE POSITION IF IT WERE LAMINAR
- for(th=0;th<threadscnt;th++) {
- laminarpitch = lampitch[th+threadbas];
- pitchwander = dz->param[STRAND_RAND] * halflamstep;
- if(th+threadbas == 0)
- pitchwander *= drand48();
- else if(th+threadbas == dz->itemcnt - 1)
- pitchwander *= -drand48();
- else
- pitchwander *= (drand48() * 2.0) - 1.0;
- laminarpitch += pitchwander;
- // INTERPOLATE btween laminar position and band-centre of twisting-threads
- if(flow_type == TOTWIST) { // as we approach true twist
- thisthreadcentre = (bandcentre - laminarpitch) * transitfrac;
- thisthreadcentre += laminarpitch;
- } else { // as we approach laminar
- thisthreadcentre = (laminarpitch - bandcentre) * transitfrac;
- thisthreadcentre += bandcentre;
- }
- // Find upper/lower limits of stream rotating around current centre (at it expands/contracts to/from full bandwidth)
- thishalfbandwidth = bandwidth/2.0;
- upbandwidth = thishalfbandwidth;
- dnbandwidth = thishalfbandwidth;
- upbandlim = thisthreadcentre + thishalfbandwidth;
- dnbandlim = thisthreadcentre - thishalfbandwidth;
- // Check total limits of band range are not exceeded
- if((xs = upbandlim - bandtop[bandno]) > 0) {
- upbandwidth -= xs;
- dnbandwidth += xs;
- } else if((xs = bandbot[bandno] - dnbandlim) > 0) {
- dnbandwidth -= xs;
- upbandwidth += xs;
- }
- // CALCULATE POSITION IN A TWIST
-
- lasttabpos = tabpos[threadbas+th];
- if(th==0)
- sinval = sinread(1,&(tabpos[threadbas]),bandtwist[bandno],&(cycend[bandno]),dz->scaler,dz);
- else
- sinval = sinread(1,&(tabpos[threadbas+th]),bandtwist[bandno],&dummycycend,dz->scaler,dz);
- // SCALE TWIST POSITION INTO THE (narrowed) RANGE AROUND THE (moving) CENTRE
-
- if(sinval >= 0.0) {
- pitch = sinval * upbandwidth; // Expand -1-to +1 range to fit into current halfbandwidth
- pitch += thisthreadcentre;
- } else {
- pitch = sinval * dnbandwidth; // NB sinval is initially -ve,
- pitch += thisthreadcentre; // so adding it to bandcentre, takes it below bandcentre
- }
- entrycnt = outcnt * 2;
- dz->parray[threadbas + th][entrycnt++] = time;
- dz->parray[threadbas + th][entrycnt++] = pitch;
- if(rotup) {
- // calculate level for laminar flow
- lamlevel = dz->param[STRAND_SCAT] * drand48();
- lamlevel = 1.0 - lamlevel;
- // calculate level for twisted flow
-
- switch(rotup) {
- case(1):
- thistabpos = lasttabpos + piover2phaseshift; // Rotating UP at the front
- while(thistabpos >= SYNTH_TABSIZE)
- thistabpos -= (double)SYNTH_TABSIZE;
- thistabpos2 = lasttabpos + piphaseshift;
- while(thistabpos2 >= SYNTH_TABSIZE)
- thistabpos2 -= (double)SYNTH_TABSIZE;
- break;
- case(-1): // Rotating DOWN at the front
- thistabpos = lasttabpos - piover2phaseshift;
- while(thistabpos < 0)
- thistabpos += (double)SYNTH_TABSIZE;
- thistabpos2 = lasttabpos;
- break;
- }
- sinval = sinread(1,&thistabpos,bandtwist[bandno],&dummycycend,dz->scaler,dz);
- level = sinval + 1.0;
- level /= 2.0;
- // Interpolate the two levels, according to
- if(flow_type == TOTWIST) // how far we are into transit to full twist
- level = (level * transitfrac) + (lamlevel * (1.0 - transitfrac));
- else // how far we are into transit to full laminar
- level = (level * (1.0 - transitfrac)) + (lamlevel * transitfrac);
- entrycnt = outcnt * 2; // Save mixdata values
- dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = time;
- dz->parray[dz->rotlevel + threadbas + th][entrycnt++] = level;
- sinval = sinread(1,&thistabpos2,bandtwist[bandno],&dummycycend,dz->scaler,dz);
- level = sinval + 1.0;
- level /= 2.0;
- // Interpolate the two mixlevels, according to
- if(flow_type == TOTWIST) // how far we are into transit to full twist
- level = level * transitfrac;
- else // how far we are into transit to full laminar
- level = level * (1.0 - transitfrac);
- entrycnt = outcnt * 2; // Save mixdata values
- dz->parray[dz->rotmix + threadbas + th][entrycnt++] = time;
- dz->parray[dz->rotmix + threadbas + th][entrycnt++] = level;
- }
- }
- rotup = -rotup;
- if(dz->mode == 2)
- threadbas += threadscnt;
- }
- break;
- }
- outcnt++;
- time = outcnt * dz->param[STRAND_TSTEP];
- flow_type = get_flow_type(time,&transitstart,&twistreffrq,&transittime,dz);
- }
- return FINISHED;
- }
- /****************************** OUTPUT_STRANDS ***********************************/
- int output_strands(char *sfnam,dataptr dz)
- {
- int exit_status, n, m, j, k;
- char temp[400];
- double *stream;
- dz->tempsize = dz->itemcnt;
- // 1st data file already open
- fprintf(stdout,"INFO: Outputting pitch-threads 1 to %d.\n",dz->itemcnt);
- fflush(stdout);
- for(n=0;n < dz->itemcnt;n++) {
- if(sloom) { // Send valid message to progress-bar
- dz->process_type = SCREEN_MESSAGE;
- dz->process = FIND_PANPOS;
- display_virtual_time(n+1,dz);
- dz->process_type = TO_TEXTFILE;
- dz->process = STRANDS;
- }
- if(n > 0) { // Current datafile closed as next is opened
- if((exit_status = create_next_outfile(n,sfnam,temp,dz))<0)
- return exit_status;
- }
- stream = dz->parray[n];
- for(m = 0, j= 0; m < dz->datasize; m++,j+=2) {
- sprintf(temp,"%.16lf\t%lf\n",stream[j],stream[j+1]);
- if(fputs(temp,dz->fp) < 0) {
- fclose(dz->fp);
- sprintf(errstr,"CANNOT WRITE PITCH DATA TO FILE %s\n",dz->outfilename);
- return SYSTEM_ERROR;
- }
- }
- }
- if(dz->iparam[STRAND_3D]) {
- fprintf(stdout,"INFO: Outputting 1st set of control threads %d to %d.\n",dz->itemcnt + 1,dz->itemcnt * 2);
- fflush(stdout);
- for(k = 0,n=dz->itemcnt;k < dz->itemcnt;n++,k++) {
- if(sloom) { // Send valid message to progress-bar
- dz->process_type = SCREEN_MESSAGE;
- dz->process = FIND_PANPOS;
- display_virtual_time(k+1,dz);
- dz->process_type = TO_TEXTFILE;
- dz->process = STRANDS;
- }
- if((exit_status = create_next_outfile(n,sfnam,temp,dz))<0)
- return exit_status;
- stream = dz->parray[dz->rotlevel + k];
- for(m = 0, j= 0; m < dz->datasize; m++,j+=2) {
- sprintf(temp,"%.16lf\t%lf\n",stream[j],stream[j+1]);
- if(fputs(temp,dz->fp) < 0) {
- fclose(dz->fp);
- sprintf(errstr,"CANNOT WRITE ROTATION-CONTROL1 DATA TO FILE %s\n",dz->outfilename);
- return SYSTEM_ERROR;
- }
- }
- }
- fprintf(stdout,"INFO: Outputting 2nd set of control threads %d to %d.\n",(dz->itemcnt*2) + 1,dz->itemcnt * 3);
- fflush(stdout);
- for(k = 0,n=dz->itemcnt*2;k < dz->itemcnt;n++,k++) {
- if(sloom) { // Send valid message to progress-bar
- dz->process_type = SCREEN_MESSAGE;
- dz->process = FIND_PANPOS;
- display_virtual_time(k+1,dz);
- dz->process_type = TO_TEXTFILE;
- dz->process = STRANDS;
- }
- if((exit_status = create_next_outfile(n,sfnam,temp,dz))<0)
- return exit_status;
- stream = dz->parray[dz->rotmix + k];
- for(m = 0, j= 0; m < dz->datasize; m++,j+=2) {
- sprintf(temp,"%.16lf\t%lf\n",stream[j],stream[j+1]);
- if(fputs(temp,dz->fp) < 0) {
- fclose(dz->fp);
- sprintf(errstr,"CANNOT WRITE ROTATION-CONTROL2 DATA TO FILE %s\n",dz->outfilename);
- return SYSTEM_ERROR;
- }
- }
- }
- } // Last datafile is closed on "complete_output"
- return FINISHED;
- }
- /**************************** CREATE_NEXT_OUTFILE ****************************/
- int create_next_outfile(int no, char *sfnam, char *temp,dataptr dz)
- {
- int exit_status;
- if(fclose(dz->fp) < 0) {
- sprintf(errstr, "Failed to close file %s\n",dz->outfilename);
- dz->process_type = OTHER_PROCESS; // prevents complaint at "complete output"
- return(GOAL_FAILED);
- }
- strcpy(dz->outfilename,sfnam);
- sprintf(temp,"%d",no);
- strcat(dz->outfilename,temp);
- if(!sloom)
- strcat(dz->outfilename,".txt");
- if((exit_status = create_sized_outfile(dz->outfilename,dz))<0) {
- sprintf(errstr, "Failed to open file %s\n",dz->outfilename);
- /*free(outfilename);*/
- dz->process_type = OTHER_PROCESS; // prevents complaint at "complete output"
- return(GOAL_FAILED);
- }
- return(FINISHED);
- }
- /**************************** SCATTER_STREAMDATA_IN_LAST_CYCLE ****************************/
- void scatter_streamdata_in_last_cycle(double time,int bandno,int threadscnt,int threadbas, int outcnt,double lastcycendtime,dataptr dz)
- {
- double warp, cyclen, timefrac;
- int n, m, k, t;
- double *thisthread;
- cyclen = time - lastcycendtime;
- for(n=0,m= threadbas;n < threadscnt;n++,m++) { // For each stream in the band
- thisthread = dz->parray[m]; // Get timewarp-value
- warp = (dz->param[STRAND_SCAT] * (STRAND_MAXWARP - 1.0)); // Range of warping, some fraction of 1-to-maxwarp range
- warp *= drand48(); // Get random value in range
- warp += 1.0; // Add back the 1, so warp in range 1 to maxwarp
- if(drand48() < 0.5)
- warp = 1.0/warp; // Warp then randomly gets value warp or 1/warp
- for(k=0,t=0;k < outcnt;k++,t+=2) { // Search the existing stored values
- if(thisthread[t] > lastcycendtime) { // For any stored value within last cycle
- timefrac = (thisthread[t] - lastcycendtime)/cyclen; // Find its time-position as a fraction of length of cycle (range 0-1)
- timefrac = pow(timefrac,warp); // Warp its time-position (also range 0-1)
- thisthread[t] = (cyclen * timefrac) + lastcycendtime; // Overwrite original timing
- }
- }
- }
- }
- /**************************** WAVY ****************************
- *
- * Motion of boundaries between bands.
- */
- double wavy(int bandno,double bandtop_mean,double tessitura,double amp,double *wavyfrq,double *tabpos,int *cycend,double scaling,dataptr dz)
- {
- double range, sinval, frqrange, frqmin, bandtop;
- sinval = sinread(0,tabpos,*wavyfrq,cycend,scaling,dz); // The tabpos is updated, the wavyfrq is fixed, the cycend is read
- range = (tessitura * WAVYFRAC) * amp;
- bandtop = bandtop_mean + (range * sinval);
- if(*cycend) { // The wavyfrq is updated only at a cycle end
- frqrange = fabs(dz->param[STRAND_VMAX] - dz->param[STRAND_VMIN]);
- frqmin = min(dz->param[STRAND_VMAX],dz->param[STRAND_VMIN]);
- *wavyfrq = drand48() * frqrange;
- *wavyfrq += frqmin;
- }
- return bandtop;
- }
- /************************************** CHECK_TWIST_VARIABLE ****************************
- *
- * Twist can be zero at start of file,
- * or be zero over a stretch of the file,
- * i.e. there can be 2 adjacent zero values, but no more or less than 2, at any one location in the file.
- */
- int establish_flow_types(dataptr dz)
- {
- int n, m, twisttime, twistval, t, v, k, f, d, lastflowtype, flowtype;
- int arraysize = dz->brksize[STRAND_TWIST];
- double *flow, lasttime;
- if(arraysize < 3)
- dz->flowcnt = 1;
- else {
- for(n=2,m= 5;n < arraysize;n++,m+=2) {
- if(twist[m] == 0.0 && twist[m-2] == 0.0 && twist[m-4] == 0.0) { // Compact any series of 3 zeros
- for(k = n*2; k < arraysize*2;k++) // So zeros only exist, at most, in pairs
- twist[k-2] = twist[k];
- arraysize--;
- n--;
- m-=2;
- }
- }
- dz->brksize[STRAND_TWIST] = arraysize;
- lastflowtype = -1;
- for(n=1,m= 3;n < arraysize;n++,m+=2) {
- if(twist[m] == 0.0 && twist[m-2] == 0.0)
- flowtype = LAMINAR;
- else if(twist[m-2] == 0.0 && twist[m] != 0.0)
- flowtype = TOTWIST;
- else if(twist[m-2] != 0.0 && twist[m] == 0.0)
- flowtype = FROMTWIST;
- else
- flowtype = TWISTED;
- if(flowtype != lastflowtype) {
- dz->flowcnt++;
- lastflowtype = flowtype;
- }
- }
- }
- if((dz->parray[dz->flowdata] = (double *)malloc((dz->flowcnt * 4) * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for storing flow-types information.\n");
- return(MEMORY_ERROR);
- }
- flow = dz->parray[dz->flowdata];
- switch(arraysize) {
- case(0):
- flow[0] = 0.0;
- if(dz->param[STRAND_TWIST] == 0) flow[1] = LAMINAR;
- else flow[1] = TWISTED;
- flow[2] = dz->param[STRAND_TWIST];
- flow[3] = dz->param[STRAND_DUR];
- break;
- case(1):
- flow[0] = 0.0;
- if(dz->brk[STRAND_TWIST][1] == 0) flow[1] = LAMINAR;
- else flow[1] = TWISTED;
- flow[2] = dz->param[STRAND_TWIST];
- flow[3] = dz->param[STRAND_DUR];
- break;
- default:
- t = 0;
- v = 1;
- f = 2;
- d = 3;
- lastflowtype = -1;
- lasttime = 0.0;
- for(n=1,twisttime = 2,twistval = 3;n < arraysize;n++,twisttime+=2,twistval+=2) {
- if(twist[twistval-2] == 0.0 && twist[twistval] == 0.0)
- flowtype = LAMINAR;
- else if(twist[twistval-2] == 0.0 && twist[twistval] != 0.0)
- flowtype = TOTWIST;
- else if(twist[twistval-2] != 0.0 && twist[twistval] == 0.0)
- flowtype = FROMTWIST;
- else
- flowtype = TWISTED;
- if(flowtype != lastflowtype) {
- flow[t] = twist[twisttime-2]; // Time of start of new flow-type
- flow[v] = flowtype; // Flow type
- flow[d] = twist[twisttime] - lasttime; // Duration of totwist or fromtwist transition (if relevant)
- lasttime = twist[twisttime];
- switch(flowtype) {
- case(TOTWIST):
- flow[f] = twist[twistval]; // Twist value at true twist start (at end of transit)
- break;
- case(FROMTWIST):
- case(TWISTED):
- flow[f] = twist[twistval-2]; // Twist value at start of transit (end of previous true-twist)
- break; // or start of true-twist (only used where flow starts with twist at time zero)
- case(LAMINAR):
- flow[f] = 0; // Value not used
- break;
- }
- t+=4;
- v+=4;
- f+=4;
- d+=4;
- lastflowtype = flowtype;
- }
- }
- flow[0] = 0.0; // Force start at zero time
- break;
- }
- return FINISHED;
- }
- /******************************************* GET_FLOW_TYPE *********************************
- *
- * Read off the type of flow being generated, from prestored table.
- */
- int get_flow_type(double time,double *transitstart,double *twistreffrq,double *transittime,dataptr dz)
- {
- double *flow = dz->parray[dz->flowdata];
- int n = 0, t = 0, flow_type;
- while(time >= flow[t]) {
- if(++n > dz->flowcnt) {
- n--;
- break;
- }
- t += 4;
- }
- t -= 4;
- *transitstart = flow[t];
- flow_type = (int)round(flow[t+1]);
- *twistreffrq = flow[t+2];
- *transittime = flow[t+3];
- return flow_type;
- }
- /******************************************* TURBLEVEL *********************************/
- double turblevel(double turbulence,double thislevel,dataptr dz)
- {
- double level;
- level = drand48();
- level = pow(level,TURBPOW);
- if(turbulence < 1.0)
- level = (level * turbulence) + (thislevel * (1.0 - turbulence));
- return level;
- }
- /******************************************* CHECK_TURBULENCE_VALUES *********************************
- *
- * Flow can be turbulent (turbulence > 0.0) where flow is TWISTED.
- */
- int check_turbulence_values(int *isturb,dataptr dz)
- {
- int exit_status, flow_type, n, ft, starttime, endtime, turbcnt, tt, vv;
- double *turb, *flow = dz->parray[dz->flowdata];
- double turbmax, turbtime, turbval, flowstart, flowend;
- // IF turbulence is fixed, and not zero
-
- if(!dz->brksize[STRAND_TURB]) {
- if(dz->param[STRAND_TURB] > 0.0) {
- *isturb = 1;
- // Turbulence everywhere: flow must be twisted everywhere
-
- for(n=0,ft = 1; n < dz->flowcnt;n++,ft+=4) {
- flow_type = (int)round(flow[ft]);
- if(flow_type != TWISTED) {
- sprintf(errstr,"Turbulence cannot exceed zero if flow is not twisted.\n");
- return DATA_ERROR;
- }
- }
- }
- } else {
- turb = dz->brk[STRAND_TURB];
- if((exit_status = get_maxvalue_in_brktable(&turbmax,STRAND_TURB,dz))<0)
- return exit_status;
- if(turbmax > 0.0)
- *isturb = 1;
- if(dz->flowcnt == 1) {
- // If only a single flow-type, this must be twisted if flow is ANYWHERE turbulent
- flow_type = (int)round(flow[1]);
- if(flow_type != TWISTED && turbmax > 0.0) {
- sprintf(errstr,"Turbulence cannot exceed zero if flow is not twisted.\n");
- return DATA_ERROR;
- }
- } else {
- // Turbulence at specific times: must coincide with twisted flow
- turbcnt = 0;
- tt = 0;
- vv = 1;
- turbtime = turb[tt];
- turbval = turb[vv];
-
- for(n=0,starttime = 0,ft = 1,endtime = 3; n < dz->flowcnt-1;n++,starttime+=4,ft+=4,endtime +=4) {
- flow_type = (int)round(flow[ft]);
-
- // Check turbulence value in all NON-twisted flows
-
- if(flow_type != TWISTED) {
- flowstart = flow[starttime];
- flowend = flow[endtime];
- while(turbtime < flowstart) { // Advance in turbulence values into next flowtype
- if(++turbcnt >= dz->brksize[STRAND_TURB])
- break;
- tt += 2;
- vv += 2;
- turbtime = turb[tt];
- turbval = turb[vv];
- }
- if(turbtime < flowstart) { // If reached end of turbulence values,
- if(turbval > 0.0) { // test last turbulence value against all further flows
- if(++n < dz->flowcnt) { // (if there are any)
- starttime += 4;
- ft += 4;
- for(;n <dz->flowcnt;n++,starttime+=4,ft+=4) {
- flow_type = (int)round(flow[ft]);
- if(flow_type != TWISTED) {
- sprintf(errstr,"Turbulence at %c in non-twisted flow.\n",starttime);
- return DATA_ERROR;
- }
- }
- }
- } // Then break out of outer test loop
- break;
- }
- // ELSE turbtime >= flowstart :
- // Test turbulence values within the NON-twisted flow
- if(turbval > 0.0) {
- sprintf(errstr,"Turbulence at %lf in non-twisted flow.\n",turbtime);
- return DATA_ERROR;
- }
- while(turbtime < flowend) {
- if(++turbcnt >= dz->brksize[STRAND_TURB])
- break;
- tt += 2;
- vv += 2;
- turbtime = turb[tt];
- turbval = turb[vv];
- if(turbval > 0.0) {
- sprintf(errstr,"Turbulence at %lf in non-twisted flow.\n",turbtime);
- return DATA_ERROR;
- }
- }
- if(turbtime < flowend) { // Reached end of turbulence values,
- if(turbval > 0.0) { // so test last turbulence value against all further flows
- if(++n < dz->flowcnt) { // (if there are any)
- starttime += 4;
- ft += 4;
- for(;n <dz->flowcnt;n++,starttime+=4,ft+=4) {
- flow_type = (int)round(flow[ft]);
- if(flow_type != TWISTED) {
- sprintf(errstr,"Turbulence at %d in non-twisted flow.\n",starttime);
- return DATA_ERROR;
- }
- }
- }
- } // Then break out of outer test loop
- break;
- }
- }
- }
- }
- }
- return FINISHED;
- }
- /********************************************** TURBULENT_BANDSWAP ********************************
- *
- * Idea here is to invert the order of threads in some pattern to force bands to cross.
- *
- * *perm points to the lowest band (&perm[threadbas]) in the current band.
- * e.g. with 4 streans per band, pointing to band 1, it points to the group perm[4][5][6][7]
- * which initially have the values 4,5,6,7
- * The process then permutes the values of this group.
- * However these are permd, this set of perm VALUES (4567) will always lie in this locations perm[4-7]
- *
- * Threads are grouped into sets of "grpcnt".
- * This grouping is selected AT RANDOM on each call.
- * Then the order in each of these group is inverted.
- *
- * There are 5 possibilities
- *
- * (1) grpcnt = streamcnt
- *
- * e.g. streamcnt = 8 A B C D E F G H
- * grpcnt = 8
- * Reverse the entire set
- * H G F E D C B A
- *
- * (2) grpcnt > 2 * streamcnt
- *
- * e.g. streamcnt = 8 A B C D E F G H
- * grpcnt = 5
- * Reverse lowest group first, then next lowest etc
- * (there will be some double reversings)
- * E D C B A f g h
- * e d c H G F A B
- *
- *
- * (3) grpcnt <= 2 * streamcnt, but divides streamcnt exactly
- *
- * e.g. streamcnt = 8 A B C D E F G H
- * grpcnt = 2
- * Reverse each group in turn
- * B A c d e f g h
- * b a D C e f g h
- * b a d c F E g h
- * b a d c f e G H
- *
- * (4) grpcnt <= 2 * streamcnt, but does NOT divide streamcnt exactly
- * And remainder is 1
- *
- * e.g. streamcnt = 7 A B C D E F G
- * grpcnt = 3
- * Reverse each complete group
- * C B A d e f g
- * c b a F E D g
- * Then rotate the whole set
- * G c b a f e d
- * OR
- * (5) grpcnt <= 2 * streamcnt, but does NOT divide streamcnt exactly
- * And remainder is > 1
- *
- * e.g. streamcnt = 8 a b c d e f g h
- * grpcnt = 3
- * Reverse each complete group, then the incomplete group
- * grpcnt = 3 C B A d e f g h
- * c b a F E D g h
- * c b a f e d H G
- *
- */
- void turbulent_bandswap(int *perm,int streamcnt)
- {
- int temp, n, m, k, setcnt, remainder;
- int gpcnt = streamcnt - 1; // e.g. with 6 streams: no of groupings = 5 (2,3,4,5,6)
- gpcnt = (int)floor(drand48() * gpcnt); // gpcnt range = 0 - 4
- gpcnt += 2; // gpcnt range = 2 - 6
- gpcnt = min(gpcnt,streamcnt); // Deal with vanishingly small probability that drand48() returns 1.0 exactly giving value 7!!
- if(gpcnt == streamcnt) { // CASE 1
- n = 0;
- m = streamcnt - 1;
- while(n < m) { // Invert entire group
- temp = perm[n];
- perm[n] = perm[m];
- perm[m] = temp;
- n++;
- m--;
- }
- } else if(gpcnt > streamcnt * 2) { // CASE 2
- n = 0;
- m = gpcnt - 1;
- while(n < m) { // Invert bottom-abutted group
- temp = perm[n];
- perm[n] = perm[m];
- perm[m] = temp;
- n++;
- m--;
- }
- n = streamcnt - gpcnt;
- m = streamcnt - 1;
- while(n < m) { // Invert top-abutted group
- temp = perm[n];
- perm[n] = perm[m];
- perm[m] = temp;
- n++;
- m--;
- }
- }
- else {
- setcnt = streamcnt/gpcnt;
- for(k=0;k<setcnt;k++) {
- n = k * gpcnt;
- m = n + gpcnt - 1;
- while(n < m) { // Invert each group in turn
- temp = perm[n];
- perm[n] = perm[m];
- perm[m] = temp;
- n++;
- m--;
- }
- }
- remainder = streamcnt%gpcnt;
- switch(remainder) {
- case(0): // CASE 3
- break;
- case(1): // CASE 4
- temp = perm[streamcnt - 1];
- n = streamcnt - 1;
- while(n > 0) { // upshufl
- perm[n] = perm[n-1];
- n--;
- } // take top to bottom
- perm[0] = temp;
- break;
- default: // CASE 5
- n = setcnt * gpcnt;
- m = streamcnt - 1;
- while(n < m) { // Invert the remnant set
- temp = perm[n];
- perm[n] = perm[m];
- perm[m] = temp;
- n++;
- m--;
- }
- break;
- }
- }
- }
- /********************************************* ASSIGN_TURBULENCE_PITCHES ********************************************
- *
- * streamcnt = no of streams in band (or total number of streams)
- * pitchbot = lowpitch boundary of band (or of entire range)
- * pitchrange = pitchwidth of band (or of entire flow)
- * perm = section of the perm array beginning at the lowest thread in this band
- * (or entire perm array for all threads)
- */
- void assign_turbulence_pitches(int streamcnt,double pitchbot,double pitchrange,int *perm,double *turbpset,double *turbpitch)
- {
- int gotit = 0, n, m;
- double maxrand = 0.0, minrand = 0.0, randrange, scaleup, temp;
- // GENERATE RANDOM VALUES WITHIN RANGE 0 to 1
- while(!gotit) {
- maxrand = 0.0;
- minrand = 1.0;
- for(n=0;n < streamcnt;n++) {
- turbpset[n] = drand48();
- minrand = min(minrand,turbpset[n]);
- maxrand = max(maxrand,turbpset[n]);
- }
- if(maxrand > minrand) // Ensure there's not a zero-spread of rand-values
- gotit = 1;
- }
- randrange = maxrand - minrand;
- scaleup = pitchrange/randrange;
- // SORT INTO ASCENDING ORDER
- for(n=0;n < streamcnt-1;n++) {
- for(m=n+1;m < streamcnt;m++) {
- if(turbpset[m] < turbpset[n]) {
- temp = turbpset[n];
- turbpset[n] = turbpset[m];
- turbpset[m] = temp;
- }
- }
- }
- // SCALE TO PITCHRANGE
- for(n=0;n < streamcnt;n++) {
- turbpset[n] -= minrand; // Move randomvalues into 0 - randrange
- turbpset[n] *= scaleup; // Scale to full pitchrange
- turbpset[n] += pitchbot; // Put in actual pitch values
- }
- turbulent_bandswap(perm,streamcnt); // Permute order of streams, so all bands cross
- for(n=0;n < streamcnt;n++) // Assign the pitches to the bands
- turbpitch[perm[n]] = turbpset[n];
- }
- /************************************ PANCALC *******************************/
- void pancalc(double position,double *leftgain,double *rightgain)
- {
- int dirflag;
- double temp;
- double relpos;
- double reldist, invsquare;
- if(position < 0.0)
- dirflag = SIGNAL_TO_LEFT; /* signal on left */
- else
- dirflag = SIGNAL_TO_RIGHT;
- if(position < 0)
- relpos = -position;
- else
- relpos = position;
- if(relpos <= 1.0){ /* between the speakers */
- temp = 1.0 + (relpos * relpos);
- reldist = ROOT2 / sqrt(temp);
- temp = (position + 1.0) / 2.0;
- *rightgain = temp * reldist;
- *leftgain = (1.0 - temp ) * reldist;
- } else { /* outside the speakers */
- temp = (relpos * relpos) + 1.0;
- reldist = sqrt(temp) / ROOT2; /* relative distance to source */
- invsquare = 1.0 / (reldist * reldist);
- if(dirflag == SIGNAL_TO_LEFT){
- *leftgain = invsquare;
- *rightgain = 0.0;
- } else { /* SIGNAL_TO_RIGHT */
- *rightgain = invsquare;
- *leftgain = 0;
- }
- }
- }
- /************************** HANDLE_THE_SPECIAL_DATA **********************************/
- int handle_the_special_data(int *cmdlinecnt,char ***cmdline,int *threadvalscnt,dataptr dz)
- {
- int cnt, *i, idummy;
- char *filename = (*cmdline)[0];
- FILE *fp;
- double dummy;
- char temp[200], *q;
- if((fp = fopen(filename,"r"))==NULL) {
- sprintf(errstr, "Can't open data file %s to read data.\n",filename);
- return(DATA_ERROR);
- }
- cnt = 0;
- while(fgets(temp,200,fp)==temp) {
- q = temp;
- if(*q == ';') // Allow comments in file
- continue;
- while(get_float_from_within_string(&q,&dummy)) {
- idummy = (int)round(dummy);
- if(idummy < 2 || idummy > 100) {
- sprintf(errstr,"Invalid thread count (%d) in file %s (Valid Range 2 - 100)\n",idummy,filename);
- return(MEMORY_ERROR);
- }
- cnt++;
- }
- }
- if(cnt == 0) {
- sprintf(errstr,"No data in data file %s\n",filename);
- return(DATA_ERROR);
- }
- if((dz->iparray = (int **)malloc(sizeof(int *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for input data in file %s.\n",filename);
- return(MEMORY_ERROR);
- }
- if((dz->iparray[0] = (int *)malloc(cnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for input data in file %s.\n",filename);
- return(MEMORY_ERROR);
- }
- fseek(fp,0,0);
- i = dz->iparray[0];
- while(fgets(temp,200,fp)==temp) {
- q = temp;
- if(*q == ';') // Allow comments in file
- continue;
- while(get_float_from_within_string(&q,&dummy)) {
- *i = (int)round(dummy);
- i++;
- }
- }
- if(fclose(fp)<0) {
- fprintf(stdout,"WARNING: Failed to close file %s.\n",filename);
- fflush(stdout);
- }
- *threadvalscnt = cnt;
- (*cmdline)++;
- (*cmdlinecnt)--;
- return(FINISHED);
- }
|