| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560 |
- /*
- * Copyright (c) 1983-2023 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
- *
- */
- #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 <standalone.h>
- #include <ctype.h>
- #include <sfsys.h>
- #include <string.h>
- #include <srates.h>
- #ifdef unix
- #include <aaio.h>
- #endif
- #if defined unix || defined __GNUC__
- #define round(x) lround((x))
- #endif
- #ifndef HUGE
- #define HUGE 3.40282347e+38F
- #endif
- // Use existing "long" items in struct "dz" to remember various process constants
- #define envcount itemcnt // Number of timed-envelope entries
- #define envsrcs ringsize // number of the array at which envelope data begins
- #define envbuf rampbrksize // number of the array where interpolated envelope is constructed
- #define outlevs temp_sampsize // number of the array where current levels on each multichan out-channel are stored
- #define fltcnt is_transpos // Constant related to the order of the filter
- #define fltmul is_flat // Filter multiplier
- #define fltractv could_be_pitch // Flags whether filtering will be required
- #define fulldur is_sharp // Duration of event
- #define SIGNAL_TO_LEFT (0) // Parameters for stereo-hole-in-middle-compensation
- #define SIGNAL_TO_RIGHT (1)
- #define ROOT2 (1.4142136)
- #define FILTER_GAIN (-96.0) // Filter gain for lo-pass filter
- #define FLT_LPHP_ARRAYS_PER_FILTER (4)
- #define FLT_DEN1 (0)
- #define FLT_DEN2 (1)
- #define FLT_CN (2)
- #define FLT_S1_BASE (3)
- #define FLT_S2_BASE (4)
- #define FLT_E1_BASE (5)
- #define FLT_E2_BASE (6)
- char errstr[2400];
- int anal_infiles = 1;
- int sloom = 0;
- int sloombatch = 0;
- const char* cdp_version = "7.1.0";
- //CDP LIB REPLACEMENTS
- static int check_fracture_param_validity_and_consistency(dataptr dz);
- static int setup_fracture_application(dataptr dz);
- static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
- static int parse_infile_and_check_type(char **cmdline,dataptr dz);
- static int setup_fracture_param_ranges_and_defaults(dataptr dz);
- static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
- static int open_the_outfile(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 fracture(int ibuflen,int envbuflen,int overflow,dataptr dz);
- static int handle_the_special_data(char *,dataptr dz);
- static int read_the_special_data(dataptr dz);
- static int fragment_param_preprocess (int *maxpulse,double *maxtrans,int *minfragmax,dataptr dz);
- static int create_fracture_sndbufs(int maxpulse,double maxtrans,int minfragmax,int *ibuflen,int *envbuflen,int *overflow,int *mbuflen,dataptr dz);
- static int read_the_envelope(double now, dataptr dz);
- static int getstakwritestt(double stakcntr,int ldur,double incr);
- static double getstakcentre(double *tempenv,dataptr dz);
- static void pancalc(double position,double *leftgain,double *rightgain);
- // mode > 0
- static int panspread(int *sectcnt,double *centre,double *spread,int *cntrswitch,int *outside,double *fmix,int samps_to_process,dataptr dz);
- static int spread_pan(double *thiscentre,int *cntrswitch,int *outside,double *spread,double *fmix,dataptr dz);
- static int filter_process(int *samps_to_process,int *endzeros,dataptr dz);
- static int do_lphp_filter_stereo(dataptr dz);
- static int lphp_filt_stereo(double *e1,double *e2,double *s1,double *s2,double *den1,double *den2,double *cn,dataptr dz,int chan);
- static int setup_lphp_filter(dataptr dz);
- static int establish_order_of_filter(double passfrq,double stopfrq,dataptr dz);
- static int allocate_internal_params_lphp(dataptr dz);
- static void calculate_filter_poles_lphp(double signd,int filter_order,double passfrq,dataptr dz);
- static void initialise_filter_coeffs_lphp(dataptr dz);
- /**************************************** MAIN *********************************************/
- int main(int argc,char *argv[])
- {
- int exit_status;
- dataptr dz = NULL;
- char **cmdline;
- int cmdlinecnt;
- int maxpulse = 0, ibuflen = 0, envbuflen = 0, minfragmax = 0, overflow = 0, mbuflen = 0;
- double maxtrans = 1.0;
- // 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 = 2;
- 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_fracture_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;
- // parse_infile_and_hone_type() =
- if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // setup_param_ranges_and_defaults() =
- if((exit_status = setup_fracture_param_ranges_and_defaults(dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // open_first_infile CDP LIB
- if((exit_status = open_first_infile(cmdline[0],dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- cmdlinecnt--;
- cmdline++;
- // 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
- if((exit_status = handle_the_special_data(cmdline[0],dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- cmdlinecnt--;
- cmdline++;
- 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);
- }
- // check_param_validity_and_consistency....
- if((exit_status = check_fracture_param_validity_and_consistency(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if((exit_status = fragment_param_preprocess(&maxpulse,&maxtrans,&minfragmax,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- is_launched = TRUE;
- if((exit_status = create_fracture_sndbufs(maxpulse,maxtrans,minfragmax,&ibuflen,&envbuflen,&overflow,&mbuflen,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if((exit_status = open_the_outfile(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if((exit_status = fracture(ibuflen,envbuflen,overflow,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 malloc changed to calloc; helps debug version 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(dataptr dz)
- {
- int exit_status;
- dz->infile->channels = dz->iparam[FRAC_CHANS];
- if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
- return(exit_status);
- dz->infile->channels = 1;
- 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_FRACTURE_APPLICATION *******************/
- int setup_fracture_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 == 0) {
- if((exit_status = set_param_data(ap,ENVSERIES,9,5,"iiDDD0000"))<0)
- return(FAILED);
- if((exit_status = set_vflgs(ap,"rpdvestSmM",10,"DDDDDDDiDD","yl",2,0,"00"))<0)
- return(FAILED);
- } else {
- if((exit_status = set_param_data(ap,ENVSERIES,9,9,"iiDDDiDdd"))<0)
- return(FAILED);
- if((exit_status = set_vflgs(ap,"rpdvesthmiazclfjkwg",19,"DDDDDDDiDDddddddddd","y",1,0,"0"))<0)
- return(FAILED);
- }
- // set_legal_infile_structure -->
- dz->has_otherfile = FALSE;
- // assign_process_logic -->
- dz->input_data_type = SNDFILES_ONLY;
- dz->process_type = UNEQUAL_SNDFILE;
- dz->outfiletype = SNDFILE_OUT;
- 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(infile_info->channels != 1) {
- sprintf(errstr,"File %s is not of correct type (must be mono)\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_FRACTURE_PARAM_RANGES_AND_DEFAULTS *******************/
- int setup_fracture_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->hi[FRAC_CHANS] = 16;
- if(dz->mode == 0) {
- ap->lo[FRAC_CHANS] = 2;
- ap->default_val[FRAC_CHANS] = 2;
- } else {
- ap->lo[FRAC_CHANS] = 4;
- ap->default_val[FRAC_CHANS] = 8;
- }
- ap->lo[FRAC_STRMS] = 4;
- ap->hi[FRAC_STRMS] = 512;
- ap->default_val[FRAC_STRMS] = 16;
- ap->lo[FRAC_PULSE] = .05;
- ap->hi[FRAC_PULSE] = 8;
- ap->default_val[FRAC_PULSE] = 1;
- ap->lo[FRAC_DEPTH] = 0;
- ap->hi[FRAC_DEPTH] = 8;
- ap->default_val[FRAC_DEPTH] = 1;
- ap->lo[FRAC_STACK] = 0;
- ap->hi[FRAC_STACK] = 12;
- ap->default_val[FRAC_STACK] = 0;
- ap->lo[FRAC_INRND] = 0;
- ap->hi[FRAC_INRND] = 1;
- ap->default_val[FRAC_INRND] = 0;
- ap->lo[FRAC_OUTRND] = 0;
- ap->hi[FRAC_OUTRND] = 1;
- ap->default_val[FRAC_OUTRND] = 0;
- ap->lo[FRAC_SCAT] = 0;
- ap->hi[FRAC_SCAT] = 1;
- ap->default_val[FRAC_SCAT] = 0;
- ap->lo[FRAC_LEVRND] = 0;
- ap->hi[FRAC_LEVRND] = 1;
- ap->default_val[FRAC_LEVRND] = 0;
- ap->lo[FRAC_ENVRND] = 0;
- ap->hi[FRAC_ENVRND] = 32767;
- ap->default_val[FRAC_ENVRND] = 0;
- ap->lo[FRAC_STKRND] = 0;
- ap->hi[FRAC_STKRND] = 1;
- ap->default_val[FRAC_STKRND] = 0;
- ap->lo[FRAC_PCHRND] = 0;
- ap->hi[FRAC_PCHRND] = 1200;
- ap->default_val[FRAC_PCHRND] = 0;
- ap->lo[FRAC_SEED] = 0;
- ap->hi[FRAC_SEED] = 32767;
- ap->default_val[FRAC_SEED] = 0;
- ap->lo[FRAC_MIN] = 0;
- ap->hi[FRAC_MIN] = 1;
- ap->default_val[FRAC_MIN] = 0;
- ap->lo[FRAC_MAX] = 0;
- ap->hi[FRAC_MAX] = 16;
- ap->default_val[FRAC_MAX] = 0;
- if(dz->mode > 0) {
- ap->lo[FRAC_CENTRE] = 0;
- ap->hi[FRAC_CENTRE] = 16;
- ap->default_val[FRAC_CENTRE] = 1;
- ap->lo[FRAC_FRONT] = -4; // -2= -infinity : further -2 allows for max-mdepth (* 2) as rear of moving-front dragged behind front
- ap->hi[FRAC_FRONT] = 2; // 2 = +infinity
- ap->default_val[FRAC_FRONT] = 0;
- ap->lo[FRAC_MDEPTH] = 0;
- ap->hi[FRAC_MDEPTH] = 1;
- ap->default_val[FRAC_MDEPTH] = 0.5;
- ap->lo[FRAC_ROLLOFF] = 0.0;
- ap->hi[FRAC_ROLLOFF] = 1.0;
- ap->default_val[FRAC_ROLLOFF] = 0.0;
- ap->lo[FRAC_ATTEN] = 1.0;
- ap->hi[FRAC_ATTEN] = 10.0;
- ap->default_val[FRAC_ATTEN] = 3.0;
- ap->lo[FRAC_ZPOINT] = 0.0;
- ap->hi[FRAC_ZPOINT] = 1.0;
- ap->default_val[FRAC_ZPOINT] = 0.66;
- ap->lo[FRAC_CONTRACT] = 0.0;
- ap->hi[FRAC_CONTRACT] = 1.0;
- ap->default_val[FRAC_CONTRACT] = 0.66;
- ap->lo[FRAC_FPOINT] = 0.0;
- ap->hi[FRAC_FPOINT] = 1.0;
- ap->default_val[FRAC_FPOINT] = 0.66;
- ap->lo[FRAC_FFACTOR] = 0.0;
- ap->hi[FRAC_FFACTOR] = 1.0;
- ap->default_val[FRAC_FFACTOR] = 0.66;
- ap->lo[FRAC_FFREQ] = 10.0;
- ap->hi[FRAC_FFREQ] = (dz->nyquist/2.0) * 0.8;
- ap->default_val[FRAC_FFREQ] = 500.0;
- ap->lo[FRAC_UP] = 0.0;
- ap->hi[FRAC_UP] = 1.0;
- ap->default_val[FRAC_UP] = 0.0;
- ap->lo[FRAC_DN] = 0.0;
- ap->hi[FRAC_DN] = 1.0;
- ap->default_val[FRAC_DN] = 0.0;
- ap->lo[FRAC_GAIN] = 0.0;
- ap->hi[FRAC_GAIN] = 1.0;
- ap->default_val[FRAC_GAIN] = 1.0;
- }
- dz->maxmode = 2;
- 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_fracture_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("fracture");
- return(USAGE_ONLY);
- }
- /**************************** CHECK_FRACTURE_PARAM_VALIDITY_AND_CONSISTENCY *****************************/
- int check_fracture_param_validity_and_consistency(dataptr dz)
- {
- int exit_status;
- double maxval, minval, xs;
- int n,m;
- if(dz->brksize[FRAC_STACK]) {
- for(n=0,m=1;n < dz->brksize[FRAC_STACK];n++,m+=2) {
- if(dz->brk[FRAC_STACK][m] <= 0.0) {
- sprintf(errstr,"Stacking value cannot be zero inside a breakpoint file,\n");
- return(DATA_ERROR);
- }
- }
- }
- if(dz->iparam[FRAC_SEED] > 0)
- srand((int)dz->iparam[FRAC_SEED]);
- if(dz->brksize[FRAC_DEPTH]) {
- if((exit_status = get_maxvalue_in_brktable(&maxval,FRAC_DEPTH,dz))<0)
- return PROGRAM_ERROR;
- } else
- maxval = dz->param[FRAC_DEPTH];
- if(maxval <= 1.0) {
- if(dz->brksize[FRAC_STACK] || (dz->param[FRAC_STACK] != 0)) {
- fprintf(stdout,"WARNING: Stack parameter set, but Depth never exceeds 1, so no stacking.\n");
- fflush(stdout);
- dz->brksize[FRAC_STACK] = 0;
- dz->param[FRAC_STACK] = 0.0;
- }
- if(dz->brksize[FRAC_STKRND] || (dz->param[FRAC_STKRND] != 0)) {
- fprintf(stdout,"WARNING: Stack randomisation parameter set, but Depth never exceeds 1, so no stacking.\n");
- fflush(stdout);
- dz->brksize[FRAC_STKRND] = 0;
- dz->param[FRAC_STKRND] = 0.0;
- }
- } else { // If stack value will be operational, if set to zero, reset NOW to 12
- if(!dz->brksize[FRAC_STACK] && dz->param[FRAC_STACK] == 0.0)
- dz->param[FRAC_STACK] = 12.0;
- }
- if(dz->mode > 0) {
- if(dz->iparam[FRAC_CHANS] % 4 != 0) {
- sprintf(errstr,"Number of output channels must be a multiple of 4.\n");
- return(DATA_ERROR);
- }
- xs = dz->param[FRAC_MDEPTH] * 2;
- if(dz->brksize[FRAC_FRONT]) {
- maxval = dz->brk[FRAC_FRONT][1];
- minval = maxval;
- for(n=1,m=3;n<dz->brksize[FRAC_FRONT];n++,m+=2) {
- if(dz->brk[FRAC_FRONT][m] > minval) {
- sprintf(errstr,"Front value must move from high values to low values,\n");
- return(DATA_ERROR);
- }
- minval = dz->brk[FRAC_FRONT][m];
- }
- dz->fulldur = dz->brk[FRAC_FRONT][(dz->brksize[FRAC_FRONT] -1) * 2];
- } else {
- dz->fulldur = dz->duration;
- maxval = dz->param[FRAC_FRONT];
- minval = dz->param[FRAC_FRONT];
- }
- dz->fltractv = 0;
- if(maxval > 1.0 || minval < -(1 + xs))
- dz->fltractv = 1;
- if(dz->param[FRAC_UP] + dz->param[FRAC_DN] >= 1.0) {
- sprintf(errstr,"Fade up and Fade down times must add up to LESS THEN 1.\n");
- return(DATA_ERROR);
- }
- dz->param[FRAC_UP] *= dz->fulldur;
- dz->param[FRAC_DN] *= dz->fulldur;
- }
- return FINISHED;
- }
- /********************************************************************************************/
- int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
- {
- if(!strcmp(prog_identifier_from_cmdline,"fracture")) dz->process = FRACTURE;
- else {
- sprintf(errstr,"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,"fracture")) {
- fprintf(stderr,
- "USAGE:fracture fracture 1\n"
- "infil outfil etab chns strms pulse edpth stkint [-hseed] [-mmin] [-imax] [-rrrnd]\n"
- "[-pprnd] [-ddisp] [-vlrnd] [-eernd] [-srnd] [-ttrnd] [-y] [-l]\n"
- "\n"
- "OR\n"
- "\n"
- "USAGE:fracture fracture 2\n"
- "infil outfil etab chns strms pulse edpth stkint cntre frnt depth rolloff [-hseed]\n"
- "[-mmin] [-imax] [-rrrnd] [-pprnd] [-ddisp] [-vlrnd] [-eernd] [-srnd] [-ttrnd]\n"
- "[-aatten] [-zzpoint] [-ccontract] [] [-llopnt] [-ffmix] [-jffrq] [-kup] [-wdn] [-y]\n"
- "\n"
- "DISPERSE MONO SIGNAL INTO FRAGMENTS SPREAD OVER N-CHANNEL SPACE.\n"
- "\n"
- "Mode 1: Output is N-channel dispersal in N-channel space.\n"
- "Mode 2: Output is stereo dispersal (posibly moving) in surround space.\n"
- "\n"
- "PRESS ANY KEY TO CONTINUE\n");
- while(!kbhit())
- ;
- if(kbhit()) {
- fprintf(stderr,
- "ETAB Textfile: Each line is a TIME followed by 7 PAIRS of envelope-data.\n"
- " envelope-data represented in form \"etime lev\"\n"
- " where \"etime\" is relative time WITHIN envelope (values between 0 & 1)\n"
- " and \"lev\" is level at etime (values 0-1). In each envelope-data set\n"
- " \"lev\" must start and end at zero and rise to a max value of 1.0\n"
- "CHNS Number of channels in output file (2-16). (Mode 2, multiples of 4 only).\n"
- "STRMS No. of spatial positions (streams) for resulting fragments ( >=4 ).\n"
- "PULSE Average gap btwn 1 set-of-frags (each in different strm) & next set.\n"
- " Disp = 0: all frags in sync at each (possibly randomised) pulse.\n"
- " Disp > 0: frags time-scattered around pulse centre. (see below).\n"
- "EDPTH Envelope depth. 1: env cuts down to zero, 0.75: cuts 3/4 way to zero,\n"
- "(+STACK) 0.1: cuts only 1/10 way to zero, 0: env has no effect on source.\n"
- " Once depth exceeds 1, fragments begin to stack (but NOT before)\n"
- " (i.e. transposed copies added to fragment, synced at envelope peak).\n"
- " Depth 2 -> Stack 1: 1st transposed element added at full level.\n"
- " Depth 1.5 -> Stack 06.5: 1st transpd element added at 1/2 (0.5) level.\n"
- " Depth 2.5 -> Stack 1.5: 1st added at full level, 2nd at 1/2 level etc\n"
- "STKINT Interval of (upward) transposition in stack, in semitones (0-12).\n"
- " Default(0) is read as octave(12). NO ZEROS in stack brkpoint files.\n"
- "SEED If NOT zero, repeating process with same seed gives identical output.\n"
- "MIN/MAX Minimum/maximum duration of fragments. If zero, no minimum/maximum.\n"
- "RRND Randomisation of read-time in src. Range 0-1.\n"
- "PRND Randomisation of pulse-time in output. Range 0-1.\n"
- " In both cases, Max(1) scatters in range +- half-duration of pulse.\n"
- "DISP Dispersal (scatter) of output timings between different streams.\n"
- " If pulse(+prnd) gives time \"P\", then for disp 0: all frags are at \"P\"\n"
- " for disp 1: frags scattered within max range (+- half-dur of pulse).\n"
- "LRND Randomisation of levels (volume) of fragments. Range 0 - 1.\n"
- " 0: All frags full level. 1: Frags at random levels between 0 & full.\n"
- "ERND Randomisation of envelope used. A time range (trange).\n"
- " Event at \"now\" reads etable at randtime btwn \"now\" & now-minus-trange.\n"
- "SRND Randomisation of stack. Range 0 - 1 (NB stack value (S) = DEPTH-1)\n"
- " 0: Stack value is S. 1: Stack val selected at random between 0 & S.\n"
- "TRND Random tranpose of fragments. Range 0-1200 cents (1 octave upwards).\n"
- " Event pitch randomised between pitch+trnd and pitch-trnd.\n"
- "-z Permit stacking of very short events. Default = forbid, prevent clipping.\n"
- "-l For more than 2 output chans, lspkrs assumed to encircle listeners,\n"
- " with a single lspkr at centre front.\n"
- " Setting -l flag assumes linear array, with leftmost+rightmost lspkrs.\n"
- "\n"
- "NB: STKINT, MAX, RRND, LRND, SRND and TRND are INACTIVE if depth < 1.\n"
- "All these params can timevary EXCEPT \"chns\", \"strms\" & \"seed\".\n"
- "\n"
- "PRESS KEY \"2\" TO SEE EXTRA OPTIONS AVAILABLE IN MODE 2\n"
- "OR ANY OTHER KEY TO FINISH.\n");
- }
- if(getch()=='2') {
- fprintf(stderr,
- "MODE 2 ONLY: Additional parameters.\n"
- "\n"
- "CNTRE Channel from which stereo-image spreads out.\n"
- "FRNT Output leading edge: 1 = in cntr lspkr: -1= in lspkr opposite cntr.\n"
- " 0 = on bisector of entire sound-surround space.\n"
- " 2 = infinitely far away in direction of centre,\n"
- " -(2+(depth*2)) = infinitely far away in direction opposite to centre.\n"
- " If front moves, forward movement only (no reversals of direction)\n"
- " and if doesn't go to infinity, event itself fades to 0 from midtime.\n"
- "DEPTH maximum fraction of all output chans turned on, behind front.\n"
- "ROLLOFF level fall as signal is spread over several chans. Range 0-1.\n"
- " 0 = no fall in level, 1 = level divided by number of chans in use.\n"
- "ATTEN Level Attenuation factor for distance, or sound fade-out.\n"
- " (Range >= 1 : 1 = linear).\n"
- "ZPOINT Point where image subtends zero angle(mono): 0 circle edge, 1 infinity\n"
- "CONTRACT Contraction factor narrowing distant image width (>=1 : 1= linear).\n"
- "LOPNT Distance where lopas-filtering is total ( 0 circle edge, 1 infinity.\n"
- "FMIX Factor for mixing lopas-filtrd signal into orig, with distance (>=1).\n"
- "FFREQ Lo-pass filter cut-off frequency.\n"
- "UP If NOT zero, proportion of overall dur over which event fades from 0.\n"
- " This is independent of any fadeup-with-approach-to-circle.\n"
- "DN If NOT zero, proportion of overall dur over which event fades to 0.\n"
- " This is independent of any fadeout-with-distance-from-circle.\n"
- "GAIN Overall gain (0-1). If \"contract\" is very much faster than \"atten\",\n"
- " rare possibility of overload, as signal is forced to mono.\n"
- "-z Permit stacking of very short events. Default = forbid, prevent clipping.\n"
- "\n"
- "in MODE 2, of the additional parameters, only \"frnt\" can vary in time.\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);
- }
- /******************************** FRACTURE *******************************/
- int fracture(int ibuflen,int envbuflen,int overflow,dataptr dz)
- {
- int exit_status, chans, tim, lev, stim, etim, toget, thistack, filter_state = 0, dostack;
- double srate = (double)dz->infile->srate, maxsamp = 0.0, normaliser;
- int n, m, total_samps_written = 0, end_read_buf_at = -1, start_read_buf_at = 0;
- int strmcnt = dz->iparam[FRAC_STRMS];
- /*
- * LONG ARRAYS: S = number of streams iptr (start of read WITHIN current input buffer, for each stream)
- * | temp storage of event starttimes
- * |---------------|---------------| | |
- * | segendsamp | inreadsamp | | | NB segendsamp is in MONO samps
- * address 0 S 2S| | need to change to (segendsamp * chans)
- * | | | 2S+1 + lmost(rmost) % dz->buflen
- * array | maxevents | maxevents | | | for write!!
- * length | | strmcnt
- * | | | strmcnt
- */
- int **evend = dz->lparray, **iread = dz->lparray + strmcnt; // Event endtime & input-read position, for each \fragment in each stream in each event-group
- int *iptr = dz->lparray[2*strmcnt]; // Pointers into input buffer, for each stream in current event-group
- int *evstt = dz->lparray[(2*strmcnt)+1]; // Envelope starttime in each stream in current event-group
- /*
- * DOUBLE ARRAYS: S = number of streams | llev
- * | | | rlev
- * |---------------|---------------|---------------|---------------|---------------| | pos
- * | depth | level | transpos | envreadtime | stacking | | | tempenv
- * | | | | | 5S| | | envdata
- * | | | | | | 5S+1| | stakcentre
- * address 0 S 2S 3S 4S | | 5S+2| | grptimes
- * | | | | | | | | 5S+3| | |
- * | | | | | | | | | 5S+4| |
- * array | maxevents | maxevents | maxevents | maxevents | maxevents | | | | | 5S+5|
- * length | | | | | S S S | | | 5S+6
- * | | | | | | | | 14| | | |
- * | | | | | | | | | dz->envcount * 15
- * | | | | | | | | | | S | |
- * | | | | | | | | | | | maxevents
- */
- double **depth = dz->parray; // Envelope (end) depth for each event in each stream
- double **evlev = dz->parray + strmcnt; // Level for each event in each stream
- double **evpch = dz->parray + (2 * strmcnt); // Transposition for each event in each stream
- double **eread = dz->parray + (3 * strmcnt); // Position to read envelope table for each event in each stream
- double **stakk = dz->parray + (4 * strmcnt); // Stacking value for each event in each stream
- double *llev = dz->parray[5 * strmcnt], *rlev = dz->parray[(5 * strmcnt)+1]; // Left and Right level for each stream, to create correct positioning
- double *tempenv = dz->parray[dz->envbuf]; // Temporary envelope store
- double *stkcntr = dz->parray[(5 * strmcnt)+5]; // Central peak of current envelope for each stream
- double *gptime = dz->parray[(5 * strmcnt)+6]; // group-Timing of events (for reading brktables)
- /*
- * INTEGER ARRAYS: S = number of streams
- *
- * lmost
- * | rmost
- * | | |
- * address 0 1 |
- * | | |
- * array S S |
- * length | | |
- */
- int *lmost = dz->iparray[0], *rmost = dz->iparray[1]; // Left & right lspkr for each stream
- /*
- * SOUND BUFFERS
- * | input | enveloping| stacking | output | overflow |
- *
- */
- float *ibuf = dz->sampbuf[0];
- float *ebuf = dz->sampbuf[1];
- float *stkbuf= dz->sampbuf[2];
- float *obuf = dz->sampbuf[3];
- float *ovflw = dz->sampbuf[4];
- int write_end = 0;
- double gp_stependtime = 0.0, last_gp_stependtime = 0.0, time, endtime, readtime;
- double init_depth, startdepth, enddepth, depthchange, thisdepth;
- double gp_stepdur, last_gp_stepdur = 0.0, randscat, maxeoffset, stack, this_stack, level, lbas, tdiff, ldiff, eval, frac;
- double transpos, incr, dsampcnt, loval, hival, diff, val, levrand, outincr, dipos, centre = 0.0;
- int losamp, hisamp, sectcnt = 0, cntrswitch = 0, outside = 0;
- int evcnt = 0, total_evcnt, minevstt, minread = 0, maxread = 0, ldur, sampcnt, stakwrite_at, opos, lpos, rpos, samps_to_write, iposlo, iposhi;
- int samps_to_read, samps_read, this_write_end, evlen, endevent, endeventend, fracmax = 0, endzeros = 0, samps_to_process;
- int display_limit = 2 * dz->infile->srate, this_display_limit = display_limit;
- double maxscatrange, lastev, offset, scatter_ambit_stt, scatter_ambit_end, available_dur, spread = 0.0, fmix = 0.0, prand;
- if(dz->mode == 0)
- chans = dz->iparam[FRAC_CHANS];
- else
- chans = STEREO; // Process initially creates stereo image which is then dispersed over multichannel space
- fprintf(stdout,"INFO: Level Check at %lf secs\n",(double)(total_samps_written/chans)/srate);
- fflush(stdout);
- while(gp_stependtime < dz->duration) {
- time = gp_stependtime; // Set start-time to end of last GROUP step
- gptime[evcnt] = time;
- if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
- return exit_status;
- if(dz->param[FRAC_MAX] > 0.0 && dz->param[FRAC_MIN] >= dz->param[FRAC_MAX]) {
- sprintf(errstr,"Max (%lf) and min (%lf) fragment-lengths incompatible at %lf secs\n",
- dz->param[FRAC_MIN],dz->param[FRAC_MAX],time);
- return DATA_ERROR;
- }
- dz->iparam[FRAC_MAX] = (int)ceil(dz->param[FRAC_MAX] * srate);
- init_depth = dz->param[FRAC_DEPTH]; // Initial depth retained here for first event
-
- // SET THE STREAMS-GROUP END-POSITION, POSSIBLY RANDOMISED
-
- gp_stepdur = dz->param[FRAC_PULSE]; // Get duration of this step
- if(dz->param[FRAC_OUTRND] > 0.0) { // If ness, random scatter this
- randscat = (drand48() * 2.0) - 1.0; // Range -1 to +1
- randscat *= gp_stepdur/2.0; // Range (1/2*stepdur) to (3/2*stepdur)
- gp_stepdur += randscat; // Modify grp-stepdur
- }
- gp_stependtime = time + gp_stepdur; // This will be start of next event
- // GET THE EVENT START AND END WRITE POSITIONS FOR EACH STREAM (POSSIBLT SCATTERED)
- for(n=0;n<strmcnt;n++) { // Note the start sample of events in each stream
- if(evcnt == 0)
- evstt[n] = 0; // First events start at file start
- else // Later events start where previous stream-event ended
- evstt[n] = evend[n][evcnt-1];
- }
- maxscatrange = gp_stepdur/2.0; // Max range (+ve or -ve) over which events can be scattered
- for(n=0;n<strmcnt;n++) { // Get the output end-timings of the streams
- endtime = gp_stependtime; // Do scattering, if required
- if(dz->param[FRAC_SCAT] > 0.0) { // Around the (already rand-offset) end-timing of the group
- if(dz->param[FRAC_MIN] > 0.0) {
- scatter_ambit_stt = gp_stependtime - maxscatrange;
- scatter_ambit_end = gp_stependtime + maxscatrange;
- if(evcnt == 0)
- lastev = 0.0;
- else
- lastev = (evend[n][evcnt-1])/srate; // End time of previous event
- available_dur = scatter_ambit_end - lastev;
- if(available_dur <= dz->param[FRAC_MIN]) { // If insufficient space for min-dur fragment
- if(evcnt == 0)
- evend[n][evcnt] = 0;
- else
- evend[n][evcnt] = evend[n][evcnt-1]; // Reduce event length to zero i.e. eliminate the event
- continue;
- } else {
- endtime = lastev + dz->param[FRAC_MIN]; // Move base of rand-vary to min-duration point
- if(endtime >= scatter_ambit_stt) { // If the min length falls inside ambit of current gp-position
- available_dur -= dz->param[FRAC_MIN]; // Length to scatter-amongst is what remains
- } else { // If NOT
- endtime = scatter_ambit_stt; // force base into ambit of current gp-position
- available_dur = maxscatrange * 2.0; // Length to scatter-amongst is whole ambit around gp-position
- }
- // Do randomisation within the remaining range
- randscat = drand48(); // Range 0 to 1
- randscat *= available_dur * dz->param[FRAC_SCAT];
- }
- } else {
- randscat = (drand48() * 2) - 1.0; // Range -1 to 1
- if(evcnt > 0) {
- lastev = (evend[n][evcnt-1])/srate; // End time of previous event
- offset = gp_stependtime - lastev; // Time between end of last event and current event_group centre
- if(offset <= 0) { // Previous event end is beyond current gpevent-end
- evend[n][evcnt] = evend[n][evcnt-1]; // Reduce event length to zero i.e. eliminate the event
- continue;
- } else if(offset < maxscatrange && randscat < 0.0) // If scattering DOWN, and offset smaller than maxrange
- randscat *= offset * dz->param[FRAC_SCAT]; // Scatter within offset
- else // In all other cases, scatter within true maxrange
- randscat *= maxscatrange * dz->param[FRAC_SCAT];
- } else
- randscat *= maxscatrange * dz->param[FRAC_SCAT];
-
- }
- endtime += randscat; // Use the actual group step-position as basis to calc rand-offsets
- }
- evend[n][evcnt] = (int)round(endtime * srate);
- }
- // DECIDE IF A WRITE-OUTBUF IS REQUIRED, AND IF SO, DO IT
- minevstt = evstt[0]; // Find minimum event start
- for(n=1;n<strmcnt;n++)
- minevstt = min(minevstt,evstt[n]);
- minevstt *= chans; // Convert to frame of output (has more channels)
- minevstt -= total_samps_written; // Convert to frame of output-buffer
- if(minevstt >= dz->buflen) { // If next write will start at or after buffer end
- if(total_samps_written/chans > this_display_limit) {
- fprintf(stdout,"INFO: Level Check at %lf secs\n",(double)(total_samps_written/chans)/srate);
- fflush(stdout);
- this_display_limit += display_limit;
- }
- for(n=0;n < dz->buflen;n++) // "Write", copy overflow back, zero overflow
- maxsamp = max(maxsamp,fabs(obuf[n]));
- total_samps_written += dz->buflen;
- write_end -= dz->buflen;
- for(n = 0;n < write_end;n++) // Copy back overflow into obuf (overflow may be longer than obuf)
- obuf[n] = ovflw[n]; // and zero remainder of overflow
- memset((char *)(obuf+write_end),0,(dz->buflen + overflow - write_end) * sizeof(float));
- }
- // FIND END DEPTH OF EACH STREAM
-
- for(n=0;n<strmcnt;n++) {
- endtime = (double)(evend[n][evcnt])/srate; // Get true endtime of stream-event
- if(dz->brksize[FRAC_DEPTH]) {
- if((exit_status = read_value_from_brktable(endtime,FRAC_DEPTH,dz))<0)
- return(exit_status); // And read depth at end of event
- }
- depth[n][evcnt] = dz->param[FRAC_DEPTH];
- }
- // FIND READ SAMPLE OF EACH STREAM, (RANDOMISED IF REQUIRED) AND MAX AND MINIMUM READ
- if(evcnt == 0) { // At very start, all segments are read at 0
- for(n=0;n<strmcnt;n++)
- iread[n][evcnt] = 0;
- minread = 0;
- maxread = 0;
- for(n=0;n<strmcnt;n++)
- maxread = max(maxread,evend[n][evcnt]);
-
- startdepth = init_depth; // Depth already read at start of loop
- enddepth = depth[n][evcnt];
- if(startdepth < 1 || enddepth < 1) // If envelopes don't cut down to zero at both ends
- fracmax = 0;
- else
- fracmax = dz->iparam[FRAC_MAX];
- } else {
- for(n=0;n<strmcnt;n++) { // Scatter the output read-timings for the streams (if ness)
- startdepth = depth[n][evcnt - 1]; // Startdepth = previous end-depth
- enddepth = depth[n][evcnt];
- if(startdepth < 1 || enddepth < 1) { // If envelopes don't cut down to zero at both ends
- iread[n][evcnt] = evend[n][evcnt - 1]; // reads & writes in same place, avoid discontinuity in output sig
- fracmax = 0;
- } else {
- readtime = last_gp_stependtime;
- if(dz->param[FRAC_INRND] > 0) {
- randscat = (drand48() * 2) - 1.0; // Around the timing START of the group
- randscat *= (last_gp_stepdur/2.0) * dz->param[FRAC_INRND];
- readtime += randscat;// Using the actual group step-duration as basis to calc rand offsets
- }
- iread[n][evcnt] = (int)round(readtime * srate);
- fracmax = dz->iparam[FRAC_MAX];
- }
- evlen = evend[n][evcnt] - evend[n][evcnt-1];
- if(fracmax > 0)
- evlen = min(evlen,fracmax);
- if(n==0) {
- minread = iread[n][evcnt];
- maxread = iread[n][evcnt] + evlen;
- } else {
- minread = min(iread[n][evcnt],minread);
- maxread = max(iread[n][evcnt] + evlen,maxread);
- }
- }
- }
-
- // SEARCH TO APPROPRIATE PLACE IN INPUT, AND SET IPTRS
-
- if(maxread - minread > ibuflen) {
- sprintf(errstr,"INPUT BUFFERSIZE MISCALCULATION\n");
- return(PROGRAM_ERROR);
- }
- if(maxread > end_read_buf_at) {
- sndseekEx(dz->ifd[0],minread,0);
- start_read_buf_at = minread;
- samps_to_read = maxread - minread;
- memset((char *)ibuf,0,ibuflen * sizeof(float));
- if((samps_read = fgetfbufEx(ibuf,ibuflen,dz->ifd[0],0))<0) {
- sprintf(errstr,"Sound read error: %s\n",sferrstr());
- return(SYSTEM_ERROR);
- }
- if(samps_read < samps_to_read) {
- fprintf(stdout,"INFO: Ran out of input samples: Terminating.\n");
- fflush(stdout);
- break;
- }
- end_read_buf_at = start_read_buf_at + samps_read;
- }
- for(n=0;n<strmcnt;n++)
- iptr[n] = iread[n][evcnt] - start_read_buf_at;
-
- // FIND THE TIMES AT WHICH TO READ ENVELOPE-TEMPLATE, AND THE DEPTH
-
- if(evcnt == 0) { // At very start, all envelope are read at 0
- for(n=0;n<strmcnt;n++)
- eread[n][evcnt] = 0.0;
- } else { // Otherwise,
- for(n=0;n<strmcnt;n++) { // initially set envelope read position to start of segment, for each stream
- eread[n][evcnt] = (double)(evend[n][evcnt - 1])/srate;
- if(dz->param[FRAC_ENVRND] > 0.0) { // If the envelope reading is scattered over a time-range
- maxeoffset = min(dz->param[FRAC_ENVRND],eread[n][evcnt]);
- randscat = drand48() * maxeoffset; // Check timerange does not exceed "now"
- eread[n][evcnt] -= randscat; // Then generate randomisation of read position
- }
- }
- }
- for(n=0;n<strmcnt;n++) { // Find depth at end of each stream
- endtime = (double)(evend[n][evcnt])/srate; // Get true endtime of stream-event
- if(dz->brksize[FRAC_DEPTH]) {
- if((exit_status = read_value_from_brktable(endtime,FRAC_DEPTH,dz))<0)
- return(exit_status); // And read depth at end of event
- }
- depth[n][evcnt] = dz->param[FRAC_DEPTH];
- }
- // READ ENVELOPE-TEMPLATE, MODIFY DEPTHS AND TIMINGS (AND CHECK FOR STACKING)
- for(n=0;n<strmcnt;n++) { // Reads an envelope template at specified time, and modify
- read_the_envelope(eread[n][evcnt],dz); // Read from input data-envelopes to temp envelope-store "tempenv"
- stkcntr[n] = getstakcentre(tempenv,dz); // Note where the peak is, for any stacking
- // Get envelope depth+stacking value
-
- if(evcnt == 0) // At very start
- startdepth = init_depth; // Depth already read at start of loop
- else // Else
- startdepth = depth[n][evcnt - 1]; // Startdepth = previous end-depth
- enddepth = depth[n][evcnt];
- stack = 0;
- if(startdepth >= 1.0 && enddepth >= 1.0) {
-
- // If depth values beyond 1, this represents stacking.
- stack = startdepth - 1.0; // Derive stacking value from depth at start of event.
- startdepth = 1.0; // and reset depth values to depth-maxima (1.0)
- enddepth = 1.0; // NB Both depths must be 1, so envelope edges tied to zero, so stack causes no glitches
- } else {
- // If depths is not everywhere at max, interp depth data onto env
- depthchange = enddepth - startdepth;
- for(tim=0,lev=1;tim<14;tim+=2,lev+=2) {
- thisdepth = depthchange * tempenv[tim]; // Times are between 0 and 1, so time also represents FRACTION of time
- thisdepth += startdepth;
- if(thisdepth > 1.0)
- thisdepth = 1.0;
- level = 1.0 - thisdepth; // Max Depth = min env level depth 1 -> 0 level| depth 1/3 -> level2/3| depth 0 -> level 1
- level += (tempenv[lev] * thisdepth);// Env fills remaining space i.e whole space | upper 1/3 of space: | None of space, env has no effect
- tempenv[lev] = level;
- }
- }
- // COPY APPROPRIATE INPUT SAMPLES TO ENVELOPE BUFFER, AND DO ENVELOPING
-
- if(evcnt == 0)
- ldur = evend[n][0];
- else
- ldur = evend[n][evcnt] - evend[n][evcnt-1];
- if(fracmax > 0)
- ldur = min(ldur,fracmax);
- if(ldur > envbuflen) {
- sprintf(errstr,"ENVELOPE BUFFERSIZE MISCALCULATION: required sample duration = %d available envelope buffer length = %d\n",ldur,envbuflen);
- return(PROGRAM_ERROR);
- }
- memset((char *)ebuf,0,envbuflen * sizeof(float));
- memcpy((char *)ebuf,(char *)(ibuf + iptr[n]),ldur * sizeof(float));
- stim = 0;
- etim = 2;
- lbas = tempenv[stim+1]; // Start of envelope segment
- tdiff = tempenv[etim] - tempenv[stim]; // Timestep in envelope segment
- ldiff = tempenv[etim+1] - tempenv[stim+1]; // Level step in envelope segment
- for(sampcnt=0;sampcnt<ldur;sampcnt++) {
- eval = tempenv[13]; // Default to end value, in case we run off end of table
- if(etim < 14) {
- toget = 1;
- frac = (double)sampcnt/(double)ldur; // Find time-fraction
- while(frac > tempenv[etim]) { // Locate which envelope seg we're in
- stim = etim; // advancing to next where ness
- etim += 2;
- if(etim >= 14) { // Gets default value at table end
- toget = 0;
- break;
- } else {
- lbas = tempenv[stim+1]; // and resetting segment constants
- tdiff = tempenv[etim] - tempenv[stim];
- ldiff = tempenv[etim+1] - tempenv[stim+1];
- }
- }
- if(toget) { // Interp in envelope table
- eval = (frac - tempenv[stim])/tdiff;
- eval *= ldiff;
- eval += lbas;
- }
- } // Use envelope val to scale input
- ebuf[sampcnt] = (float)(ebuf[sampcnt] * eval);
- }
- // IF STACKING - IF STACKING RANDOMISED SET A STACK VALUE - STORE STACKING VALUE
- if(stack > 0) {
- dostack = 1;
- if(ldur < 8192) { // Prevent stacking of very short events
- if(!dz->vflag[0]) { // Unless allowed
- dostack = 0;
- stack = 0;
- }
- }
- if (dostack) {
- if(dz->param[FRAC_STKRND] > 0) {
- this_stack = stack;
- stack *= drand48() * dz->param[FRAC_STKRND];
- stack = this_stack - stack;
- }
- }
- }
- stakk[n][evcnt] = stack; // Store stack values for next pass
- if(stack > 0) {
- memset((char *)stkbuf,0,envbuflen * sizeof(float));
- thistack = (int)floor(stack); // e.g. 2.0 e.g. 2.3
- while(thistack > 0) { // --> 2 --> 2
- if(flteq((double)thistack,stack))
- level = 1.0; // level 1
- // trans remains 2
- else {
- level = stack - (double)thistack; // level 0.3
- thistack++; // trans 3
- }
- transpos = dz->param[FRAC_STACK] * thistack; // Derives stacking interval from multiple of stack parameter
- incr = pow(2.0,(transpos/SEMITONES_PER_OCTAVE)); // semitones to frq ratio
- stakwrite_at = getstakwritestt(stkcntr[n],ldur,incr); // Find where to start writing this particular transposition into stakbuf
- dsampcnt = 0.0;
- while(dsampcnt < ldur) { // Read the enveloped orig, with an incr that transposes it
- losamp = (int)floor(dsampcnt); // Interpolating as ness
- hisamp = losamp+1;
- frac = dsampcnt - (double)losamp;
- loval = ebuf[losamp];
- hival = ebuf[hisamp];
- diff = hival - loval;
- diff *= frac;
- val = loval + diff; // Add the interpd val into stakbuffer
- stkbuf[stakwrite_at] = (float)(stkbuf[stakwrite_at] + val); // (There may be more than 1 stack component to add)
- stakwrite_at++; // Incr normally in stacking buffer
- dsampcnt += incr; // Incr transpositionwise in read-from buff
- }
- thistack--; // -->1 --> 1
- stack = (double)thistack; // Will now generate full level for lower stack components
- }
-
- // Once all staks generated, add stacks to original envelope buffer
- for(m=0;m<ldur;m++)
- ebuf[m] = (float)(ebuf[m] + stkbuf[m]);
- }
- // IF LEVEL IS RANDOMISED, AND EVENTS ARE FULLY SEPARATED (Depth 1 at both ends) GET A RANDOM LEVEL AND APPLY IT
-
- if(startdepth >= 1.0 && enddepth >= 1.0) { // Level or pitch-shifting can only happem
- if(dz->param[FRAC_LEVRND] > 0) { // if edges of event are tied to zero-level
- levrand = drand48() * dz->param[FRAC_LEVRND];
- levrand = 1.0 - levrand;
- evlev[n][evcnt] = levrand;
- for(m=0;m<ldur;m++)
- ebuf[m] = (float)(ebuf[m] * evlev[n][evcnt]);
- } else
- evlev[n][evcnt] = 1.0;
- // IF PITCH IS RANDOMISED, GET A RANDOM PITCH-INCR READY TO READ ENVELOPED DATA TO OUTPUT BUFFER
- // IF NOT, THIS GETS VALUE 1 (No pitch change)
- if(dz->param[FRAC_PCHRND] > 0) {
- prand = drand48() * dz->param[FRAC_PCHRND];
- outincr = pow(2.0,(prand/SEMITONES_PER_OCTAVE)); // Convert from semitones to frq-ratio
- } else
- outincr = 1.0;
- evpch[n][evcnt] = outincr; // Store
- } else {
- evlev[n][evcnt] = 1.0;
- evpch[n][evcnt] = 1.0;
- outincr = 1.0;
- }
- // SAFETY CHECK FOR OUTPUT BUFFER OVERFLOW
- opos = evstt[n] * chans; // Change write position to frame of output
- opos -= total_samps_written; // Change write position to frame of output-buffer
- samps_to_write = (int)ceil((double)ldur/outincr) * chans;
- if(samps_to_write + opos >= dz->buflen + overflow) {
- sprintf(errstr,"OVERFLOW BUFFER ITSELF OVERFLOWED WHEN PITCH INCR WAS %lf.\n",outincr);
- return(PROGRAM_ERROR);
- }
- // WRITE OUTPUT
- lpos = opos + lmost[n]; // Change write position to correct left and right channels
- rpos = opos + rmost[n];
- dipos = 0.0;
- while(dipos < ldur) { // This should wraparound OK, as buffer is preset with zeros
- iposlo = (int)floor(dipos); // So wraparound sample will be zero
- iposhi = iposlo+1;
- frac = dipos - (double)iposlo;
- loval = ebuf[iposlo];
- hival = ebuf[iposhi];
- diff = hival - loval;
- diff *= frac;
- val = loval + diff; // Add the interpd enveloped-val into output buffer
- obuf[lpos] = (float)(obuf[lpos] + (val * llev[n]));
- obuf[rpos] = (float)(obuf[rpos] + (val * rlev[n]));
- dipos += outincr; // Interpolate in input (enveloped) sound
- lpos += chans; // Jump by a whole channel-group in output buffer
- rpos += chans;
- }
- this_write_end = (lpos/chans) * chans; // Round up to end of last-group written, to find end of write in buffer
- write_end = max(this_write_end,write_end); // Find write_end from all stream writes (and previous writes)
- }
-
- // ONCE ALL STREAMS ADDED TO OUTPUT
- evcnt++; // Count event
- last_gp_stependtime = gp_stependtime; // Remember startsamp and sampduration of previous group-segment
- last_gp_stepdur = gp_stepdur; // Need for generating input-read time
- }
- total_evcnt = evcnt;
- if(write_end > 0) {
- fprintf(stdout,"INFO: Level Check at %lf secs\n",(double)(total_samps_written/chans)/srate);
- fflush(stdout);
- for(n=0;n < write_end;n++) // "Write", copy overflow back, zero overflow
- maxsamp = max(maxsamp,fabs(obuf[n]));
- total_samps_written += write_end;
- }
- normaliser = 1.0;
- if(maxsamp > 0.95) {
- normaliser = 0.95/maxsamp;
- fprintf(stdout,"INFO: Normalising by %lf secs\n",(double)normaliser);
- fflush(stdout);
- }
- for(n=0;n<strmcnt;n++) { // In each stream
- endevent = evcnt-1; // Find the last active event
- endeventend = evend[n][endevent]; // i.e. last event NOT of zero length
- m = endevent - 1;
- while(m >= 0) {
- if(evend[n][m] < endeventend) // If previous event begins earlier, we've found end event
- break;
- else { // Else end of two events coincides, thus zero-length event.
- endevent = m; // Skip back over it,to find real last-active-event
- m--;
- }
- }
- depth[n][endevent] = 1; // Force this last event to fade to zero at stream's end
- }
- fprintf(stdout,"INFO: Second pass: generating output.\n");
- fflush(stdout);
- if(sloom) {
- if(dz->mode == 0)
- dz->insams[0] = total_samps_written; // This forces sloom progress bar to proceed correctly, without mod to libraries
- else
- dz->insams[0] = (total_samps_written/STEREO) * dz->iparam[FRAC_CHANS];
- }
- sndseekEx(dz->ifd[0],0,0);
- reset_filedata_counters(dz);
- memset((char *)obuf,0,(dz->buflen + overflow) * sizeof(float)); // reset output and overflow buffers
- memset((char *)ibuf,0,ibuflen * sizeof(float)); // reset input buffer
- total_samps_written = 0;
- end_read_buf_at = -1;
- start_read_buf_at = 0;
- write_end = 0;
- evcnt = 0;
- while(evcnt < total_evcnt) {
- time = gptime[evcnt]; // Set start-time to end of last GROUP step
- if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
- return exit_status;
- dz->iparam[FRAC_MAX] = (int)ceil(dz->param[FRAC_MAX] * srate);
- init_depth = dz->param[FRAC_DEPTH];
-
- // GET THE EVENT START POSITIONS FOR EACH STREAM
- for(n=0;n<strmcnt;n++) { // Note the start sample of events in each stream
- if(evcnt == 0)
- evstt[n] = 0;
- else
- evstt[n] = evend[n][evcnt-1];
- }
- // DECIDE IF A WRITE-OUTBUF IS REQUIRED, AND IF SO, DO IT
- minevstt = evstt[0]; // Find minimum event start
- for(n=1;n<strmcnt;n++)
- minevstt = min(minevstt,evstt[n]);
- minevstt *= chans; // Convert to frame of output (has more channels)
- minevstt -= total_samps_written; // Convert to frame of output-buffer
- if(minevstt >= dz->buflen) { // If next write will start at or after buffer end
- for(n=0;n < dz->buflen;n++) // Normalise, write output, copy overflow back, zero overflow
- obuf[n] = (float)(obuf[n] * normaliser);
- if(dz->mode == 0) {
- if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
- return(exit_status);
- total_samps_written += dz->buflen;
- write_end -= dz->buflen;
- for(n = 0;n < write_end;n++) // Copy back overflow into obuf (overflow may be longer than obuf)
- obuf[n] = ovflw[n]; // and zero remainder of overflow
- memset((char *)(obuf+write_end),0,(dz->buflen + overflow - write_end) * sizeof(float));
- } else {
- samps_to_process = dz->buflen;
- if(dz->fltractv) {
- if((exit_status = filter_process(&samps_to_process,&endzeros,dz))<0)
- return(exit_status);
- }
- if((exit_status = panspread(§cnt,¢re,&spread,&cntrswitch,&outside,&fmix,samps_to_process,dz))<0)
- return(exit_status);
- if(exit_status == CONTINUE) {
- total_samps_written += dz->buflen;
- write_end -= dz->buflen;
- for(n = 0;n < write_end;n++) // Copy back overflow into obuf (overflow may be longer than obuf)
- obuf[n] = ovflw[n]; // and zero remainder of overflow
- memset((char *)(obuf+write_end),0,(dz->buflen + overflow - write_end) * sizeof(float));
- } else {
- write_end = 0;
- break;
- }
- }
- }
- // FIND READ SAMPLE OF EACH STREAM, AND MAX AND MINIMUM READ
- if(evcnt == 0) { // At very start, all segments are read at 0
- minread = 0;
- maxread = 0;
- for(n=0;n<strmcnt;n++)
- maxread = max(maxread,evend[n][evcnt]);
- startdepth = init_depth; // Startdepth = previous end-depth
- enddepth = depth[n][evcnt];
- if(startdepth < 1 || enddepth < 1) // If envelopes don't cut down to zero at both ends
- fracmax = 0; // Max fragment length not used
- else
- fracmax = dz->iparam[FRAC_MAX];
- } else {
- for(n=0;n<strmcnt;n++) { // Scatter the output read-timings for the streams (if ness)
- startdepth = depth[n][evcnt - 1]; // Startdepth = previous end-depth
- enddepth = depth[n][evcnt];
- if(startdepth < 1 || enddepth < 1) // If envelopes don't cut down to zero at both ends
- fracmax = 0; // Max fragment length not used
- else
- fracmax = dz->iparam[FRAC_MAX];
- evlen = evend[n][evcnt] - evend[n][evcnt-1];
- if(fracmax > 0)
- evlen = min(evlen,fracmax);
- if(n==0) {
- minread = iread[n][evcnt];
- maxread = iread[n][evcnt] + evlen;
- } else {
- minread = min(iread[n][evcnt],minread);
- maxread = max(iread[n][evcnt] + evlen,maxread);
- }
- }
- }
- // SEARCH TO APPROPRIATE PLACE IN INPUT (IF NECESSARY), AND SET IPTRS
-
- if(maxread > end_read_buf_at) {
- sndseekEx(dz->ifd[0],minread,0);
- start_read_buf_at = minread;
- samps_to_read = maxread - minread;
- if((samps_read = fgetfbufEx(ibuf,ibuflen,dz->ifd[0],0))<0) {
- sprintf(errstr,"Sound read error: %s\n",sferrstr());
- return(SYSTEM_ERROR);
- }
- if(samps_read < samps_to_read) {
- fprintf(stdout,"WARNING: Sound Read anomaly - short buffer read, probably at end of file: Terminating.\n");
- fflush(stdout); // This shouled not happen as it's trapped on the first pass
- break;
- }
- end_read_buf_at = start_read_buf_at + samps_read;
- }
- for(n=0;n<strmcnt;n++)
- iptr[n] = iread[n][evcnt] - start_read_buf_at;
-
- // READ ENVELOPE-TEMPLATE, MODIFY DEPTHS AND TIMINGS (AND CHECK FOR STACKING)
- for(n=0;n<strmcnt;n++) { // Reads and envelope template at specified time, and modify
- read_the_envelope(eread[n][evcnt],dz); // Read from input data-envelopes to temp envelope-store "tempenv"
- stkcntr[n] = getstakcentre(tempenv,dz); // Note where the peak is, for any stacking
- // Get envelope depth+stacking value
-
- if(evcnt == 0) // At very start
- startdepth = init_depth; // Depth already read at start of loop
- else // Else
- startdepth = depth[n][evcnt - 1]; // Startdepth = previous end-depth
- enddepth = depth[n][evcnt];
- if(startdepth >= 1.0 && enddepth >= 1.0) {
- startdepth = 1.0;
- enddepth = 1.0;
- } else {
- depthchange = enddepth - startdepth;
- for(tim=0,lev=1;tim<14;tim+=2,lev+=2) {
- thisdepth = depthchange * tempenv[tim]; // Times are between 0 and 1, so time also represents FRACTION of time
- thisdepth += startdepth;
- if(thisdepth > 1.0)
- thisdepth = 1.0;
- level = 1.0 - thisdepth; // Max Depth = min env level depth 1 -> 0 level| depth 1/3 -> level2/3| depth 0 -> level 1
- level += (tempenv[lev] * thisdepth);// Env fills remaining space i.e whole space | upper 1/3 of space: | None of space, env has no effect
- tempenv[lev] = level;
- }
- }
- // COPY APPROPRIATE INPUT SAMPLES TO ENVELOPE BUFFER, AND DO ENVELOPING
-
- if(evcnt == 0)
- ldur = evend[n][0];
- else
- ldur = evend[n][evcnt] - evend[n][evcnt-1];
- if(fracmax > 0)
- ldur = min(ldur,fracmax);
- memset((char *)ebuf,0,envbuflen * sizeof(float));
- memcpy((char *)ebuf,(char *)(ibuf + iptr[n]),ldur * sizeof(float));
- stim = 0;
- etim = 2;
- lbas = tempenv[stim+1]; // Start of envelope segment
- tdiff = tempenv[etim] - tempenv[stim]; // Timestep in envelope segment
- ldiff = tempenv[etim+1] - tempenv[stim+1]; // Level step in envelope segment
- for(sampcnt=0;sampcnt<ldur;sampcnt++) {
- eval = tempenv[13]; // Default to end value, in case we run off end of table
- if(etim < 14) {
- toget = 1;
- frac = (double)sampcnt/(double)ldur; // Find time-fraction
- while(frac > tempenv[etim]) { // Locate which envelope seg we're in
- stim = etim; // advancing to next where ness
- etim += 2;
- if(etim >= 14) {
- toget = 0;
- break;
- } else {
- lbas = tempenv[stim+1]; // and resetting segment constants
- tdiff = tempenv[etim] - tempenv[stim];
- ldiff = tempenv[etim+1] - tempenv[stim+1];
- }
- }
- if(toget) { // Interp in envelope table
- eval = (frac - tempenv[stim])/tdiff;
- eval *= ldiff;
- eval += lbas;
- }
- } // Use envelope val to scale input
- ebuf[sampcnt] = (float)(ebuf[sampcnt] * eval);
- }
- // IF STACKING - DO STACKING
- stack = stakk[n][evcnt];
- if(stack > 0) {
- memset((char *)stkbuf,0,envbuflen * sizeof(float));
- thistack = (int)floor(stack); // e.g. 2.0 e.g. 2.3
- while(thistack > 0) { // --> 2 --> 2
- if(flteq((double)thistack,stack))
- level = 1.0; // level 1
- // trans remains 2
- else {
- level = stack - (double)thistack; // level 0.3
- transpos = dz->param[FRAC_STACK] * (1 + thistack); // trans 3
- }
- transpos = dz->param[FRAC_STACK] * thistack; // Derives stacking interval from multiple of stack parameter
- incr = pow(2.0,(transpos/SEMITONES_PER_OCTAVE)); // semitones to frq ratio
- stakwrite_at = getstakwritestt(stkcntr[n],ldur,incr); // Find where to start writing this particular transposition into stakbuf
- dsampcnt = 0.0;
- while(dsampcnt < ldur) { // Read the enveloped orig, with an incr that transposes it
- losamp = (int)floor(dsampcnt); // Interpolating as ness
- hisamp = losamp+1;
- frac = dsampcnt - (double)losamp;
- loval = ebuf[losamp];
- hival = ebuf[hisamp];
- diff = hival - loval;
- diff *= frac;
- val = loval + diff; // Add the interpd val into stakbuffer
- stkbuf[stakwrite_at] = (float)(stkbuf[stakwrite_at] + val); // (There may be more than 1 stack component to add)
- stakwrite_at++; // Incr normally in stacking buffer
- dsampcnt += incr; // Incr transpositionwise in read-from buff
- }
- thistack--; // -->1 --> 1
- stack = (double)thistack; // Will now generate full level for lower stack components
- }
-
- // Once all staks generated, add stacks to original envelope buffer
- for(m=0;m<ldur;m++)
- ebuf[m] = (float)(ebuf[m] + stkbuf[m]);
- }
- // IF LEVEL IS NOT 1.0, APPLY IT
- if(!flteq(evlev[n][evcnt],1.0)) {
- for(m=0;m<ldur;m++)
- ebuf[m] = (float)(ebuf[m] * evlev[n][evcnt]);
- }
-
- // GET PITCH-INCR
- outincr = evpch[n][evcnt];
- // WRITE TO OUTPUT BUF WITH APPROPRIATE PITCHSHIFT, AND SPATIALISATION
- opos = evstt[n] * chans; // Change write position to frame of output
- opos -= total_samps_written; // Change write position to frame of output-buffer
- lpos = opos + lmost[n]; // Change write position to correct left and right channels
- rpos = opos + rmost[n];
- dipos = 0.0;
- while(dipos < ldur) { // This should wraparound OK, as buffer is preset with zeros
- iposlo = (int)floor(dipos); // So wraparound sample will be zero
- iposhi = iposlo+1;
- frac = dipos - (double)iposlo;
- loval = ebuf[iposlo];
- hival = ebuf[iposhi];
- diff = hival - loval;
- diff *= frac;
- val = loval + diff; // Add the interpd enveloped-val into output buffer
- obuf[lpos] = (float)(obuf[lpos] + (val * llev[n]));
- obuf[rpos] = (float)(obuf[rpos] + (val * rlev[n]));
- dipos += outincr; // Interpolate in input (enveloped) sound
- lpos += chans; // Jump by a whole channel-group in output buffer
- rpos += chans;
- }
- this_write_end = (lpos/chans) * chans; // Round up to end of last-group written, to find end of write in buffer
- write_end = max(this_write_end,write_end); // Find write_end from all stream writes (and previous writes)
- }
- evcnt++; // Count event
- }
- if(write_end > 0) {
- for(n=0;n < write_end;n++) // Normalise remainder of output (ALL OF IT)
- obuf[n] = (float)(obuf[n] * normaliser);
- if(dz->mode == 0) { // In mode 0, write all of remaining output
- if((exit_status = write_samps(obuf,write_end,dz))<0)
- return(exit_status);
- } else { // In mode > 0, process output in chunks of buflen samps (or less)
- while(write_end > dz->buflen) {
- samps_to_process = dz->buflen;
- if(dz->fltractv) {
- if((exit_status = filter_process(&samps_to_process,&endzeros,dz))<0)
- return(exit_status);
- }
- if((exit_status = panspread(§cnt,¢re,&spread,&cntrswitch,&outside,&fmix,dz->buflen,dz))<0)
- return(exit_status);
- if(exit_status == CONTINUE) {
- write_end -= dz->buflen;
- for(n = 0;n < write_end;n++) // Copy back overflow into obuf (overflow may be longer than obuf)
- obuf[n] = ovflw[n]; // and zero remainder of overflow
- memset((char *)(obuf+write_end),0,(dz->buflen + overflow - write_end) * sizeof(float));
- } else {
- write_end = 0;
- break;
- }
- }
- if(dz->fltractv) { // In the fitered case, filter will continue to output, even if no input
- samps_to_process = write_end;
- do {
- if((exit_status = filter_process(&samps_to_process,&endzeros,dz))<0)
- return(exit_status); // Filter returns number of samples that are not (trailing) zeros
- filter_state = exit_status; // & filter_state = CONTINUE if not at end of its data, or FINISHED if reached end
- if(samps_to_process) { // Only spatialise data if filter outputs some data ...
- if((exit_status = panspread(§cnt,¢re,&spread,&cntrswitch,&outside,&fmix,samps_to_process,dz))<0)
- return(exit_status);
- } // Quit this loop once filter runs to stream of zeros (filter_state = FINISHED)
- samps_to_process = 0; // After first buffer, no samples are being sent to filter
- } while(filter_state == CONTINUE);
- } else if(write_end > 0) {
- if((exit_status = panspread(§cnt,¢re,&spread,&cntrswitch,&outside,&fmix,write_end,dz))<0)
- return(exit_status);
- }
- }
- }
- return FINISHED;
- }
- /****************************** GET_MODE *********************************/
- int get_the_mode_from_cmdline(char *str,dataptr dz)
- {
- char temp[200], *p;
- if(sscanf(str,"%s",temp)!=1) {
- sprintf(errstr,"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);
- }
- /**************************** HANDLE_THE_SPECIAL_DATA ****************************/
- int handle_the_special_data(char *str,dataptr dz)
- {
- int exit_status;
- double dummy = 0.0, lasttime = 0.0, lastetime = 0.0, maxlevel = 0.0;
- FILE *fp;
- int cnt, linecnt;
- char temp[800], *p;
- if((fp = fopen(str,"r"))==NULL) {
- sprintf(errstr,"Cannot open file %s to read times.\n",str);
- return(DATA_ERROR);
- }
- linecnt = 0;
- while(fgets(temp,200,fp)!=NULL) {
- p = temp;
- while(isspace(*p))
- p++;
- if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
- continue;
- cnt = 0;
- while(get_float_from_within_string(&p,&dummy)) {
- switch(cnt) {
- case(0):
- if(linecnt == 0) {
- if(dummy != 0) {
- sprintf(errstr,"First time (first entry in first line) in envelopes data (%lf) must be zero.\n",dummy);
- return(DATA_ERROR);
- } else
- lasttime = dummy;
- } else {
- if(dummy <= lasttime) {
- sprintf(errstr,"Times (first entry) do not advance at line %d in transpositions data.\n",linecnt+1);
- return(DATA_ERROR);
- }
- }
- break;
- case(1):
- if(dummy != 0) {
- sprintf(errstr,"First envelope time (2nd entry) (%lf) in envelope data line (%d) must be zero.\n",dummy,linecnt+1);
- return(DATA_ERROR);
- }
- lastetime = dummy;
- break;
- case(2):
- if(dummy != 0) {
- sprintf(errstr,"First level (3rd entry) (%lf) in envelope data line (%d) must be zero.\n",dummy,linecnt+1);
- return(DATA_ERROR);
- }
- maxlevel = dummy;
- break;
- case(13):
- if(!flteq(dummy,1.0)) {
- sprintf(errstr,"Last envelope time (14th entry) (%lf) in envelope data line (%d) must be ONE.\n",dummy,linecnt+1);
- return(DATA_ERROR);
- }
- break;
- case(14):
- if(dummy != 0) {
- sprintf(errstr,"Last level (15th entry) (%lf) in envelope data line (%d) must be zero.\n",dummy,linecnt+1);
- return(DATA_ERROR);
- }
- break;
- default:
- if(dummy < 0.0 || dummy > 1.0) {
- sprintf(errstr,"Values and envelope-times in envelope data must lie between 0 and 1 (see line %d).\n",linecnt+1);
- return(DATA_ERROR);
- }
- if(ODD(cnt)) { // ODD entries, envelope-time
- if(dummy <= lastetime) {
- sprintf(errstr,"Envelope times do not increase at entry %d in line %d.\n",cnt+1,linecnt+1);
- return(DATA_ERROR);
- }
- lastetime = dummy;
- } else
- maxlevel = max(dummy,maxlevel);
- break;
- }
- cnt++;
- }
- if(cnt != 15) {
- sprintf(errstr,"Invalid number of entries (%d) on line %d: should be 15 (1 time plus 7-etime-level pairs\n",cnt,linecnt+1);
- return(DATA_ERROR);
- }
- if(!flteq(maxlevel,1.0)) {
- sprintf(errstr,"Envelope data in line %d does not rise to maximum of 1.0.\n",linecnt+1);
- return(DATA_ERROR);
- }
- linecnt++;
- }
- if(linecnt == 0) {
- sprintf(errstr,"No data found in envelope data file.\n");
- return(DATA_ERROR);
- }
- dz->envcount = linecnt; // Number of different envelopes ....
- dz->all_words = 0;
- if((exit_status = store_filename(str,dz))<0)
- return(exit_status);
- fclose(fp);
- return FINISHED;
- }
- /**************************** READ_THE_SPECIAL_DATA ****************************/
- int read_the_special_data(dataptr dz)
- {
- double *envdata, dummy;
- FILE *fp;
- int cnt;
- char temp[800], *p;
- envdata = dz->parray[dz->envsrcs];
- if((fp = fopen(dz->wordstor[0],"r"))==NULL) {
- sprintf(errstr,"Cannot open file %s to envelope data times.\n",dz->wordstor[0]);
- return(DATA_ERROR);
- }
- cnt = 0;
- while(fgets(temp,200,fp)!=NULL) {
- p = temp;
- while(isspace(*p))
- p++;
- if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
- continue;
- while(get_float_from_within_string(&p,&dummy)) {
- envdata[cnt] = dummy;
- cnt++;
- }
- }
- return FINISHED;
- }
- /**************************** FRAGMENT_PARAM_PREPROCESS ****************************/
- int fragment_param_preprocess (int *maxpulse,double *maxtrans,int *minfragmax,dataptr dz)
- {
- int exit_status, chans, strmcnt;
- int n, m, eventcnt;
- double d_minpulse, d_maxpulse, d_minfragmax, srate, leftgain, rightgain, val;
- int *lmost, *rmost;
- double *llev, *rlev, *pos;
- if(dz->mode == 0)
- chans = dz->iparam[FRAC_CHANS];
- else
- chans = STEREO;
- strmcnt = dz->iparam[FRAC_STRMS];
- srate = (double)dz->infile->srate;
- if(dz->brksize[FRAC_PCHRND]) {
- for(n=0,m=1;n < dz->brksize[FRAC_PCHRND];n++,m+=2) {
- val = dz->brk[FRAC_PCHRND][m];
- val /= 100.0; // Convert from cents to semitones
- dz->brk[FRAC_PCHRND][m] = val;
- }
- if((exit_status = get_maxvalue_in_brktable(&val,FRAC_PCHRND,dz))<0)
- return PROGRAM_ERROR;
- *maxtrans = pow(2.0,(val/SEMITONES_PER_OCTAVE));
- } else {
- dz->param[FRAC_PCHRND] /= 100.0;
- val = dz->param[FRAC_PCHRND];
- *maxtrans = pow(2.0,(val/SEMITONES_PER_OCTAVE)); // Retain max transposition for calculation of buffer sizes
- }
- if(dz->brksize[FRAC_MIN]) {
- if((exit_status = get_maxvalue_in_brktable(&d_minfragmax,FRAC_MIN,dz))<0)
- return PROGRAM_ERROR;
- } else
- d_minfragmax = dz->param[FRAC_MIN];
- *minfragmax = (int)ceil(d_minfragmax * srate);
- if(dz->brksize[FRAC_PULSE]) {
- if((exit_status = get_minvalue_in_brktable(&d_minpulse,FRAC_PULSE,dz))<0)
- return PROGRAM_ERROR;
- if((exit_status = get_maxvalue_in_brktable(&d_maxpulse,FRAC_PULSE,dz))<0)
- return PROGRAM_ERROR;
- } else {
- d_minpulse = dz->param[FRAC_PULSE];
- d_maxpulse = dz->param[FRAC_PULSE];
- }
- d_maxpulse *= 2.0; // Allow for maximum randomisation extension of pulse-duration = 1/2 pulse dur, but at BOTH ends
- *maxpulse = (int)ceil(d_maxpulse * srate);
- d_minpulse /= 2.0; // Allow for maximum randomisation reduction of pulse-duration
- eventcnt = (int)ceil(dz->duration/d_minpulse) + 16; // SAFETY
- /*
- * DOUBLE ARRAYS: S = number of streams | llev
- * | | | rlev
- * |---------------|---------------|---------------|---------------|---------------| | pos
- * | depth | level | transpos | envreadtime | stacking | | | tempenv
- * | | | | | 5S| | | envdata
- * | | | | | | 5S+1| | stakcentre
- * address 0 S 2S 3S 4S | | 5S+2| | grptimes
- * | | | | | | | | 5S+3| | chan-levels(mode>0 only)
- * | | | | | | | | | 5S+4| | |
- * array | maxevents | maxevents | maxevents | maxevents | maxevents | | | | | 5S+5| |
- * length | | | | | S S S | | | 5S+6| then 11 filter arrays
- * | | | | | | | | 14| | | | |
- * | | | | | | | | | dz->envcount * 15
- * | | | | | | | | | | S | | |
- * | | | | | | | | | | | maxevents
- * | | | | | | | outchans
- */
- if((dz->parray = (double **)malloc(((strmcnt * 5) + 19) * sizeof(double *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for double arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0,m=1;n<strmcnt;n++,m++) { // Envelope depth/stack of each-event-in-each-stream
- if((dz->parray[n] = (double *)malloc(eventcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d depth array.\n",m);
- return(MEMORY_ERROR);
- }
- }
- for(m=1;n<strmcnt*2;n++,m++) { // Level of each-event-in-each-stream
- if((dz->parray[n] = (double *)malloc(eventcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d level array.\n",m);
- return(MEMORY_ERROR);
- }
- }
- for(m=1;n<strmcnt*3;n++,m++) { // Transpos for each-event-in-each-stream
- if((dz->parray[n] = (double *)malloc(eventcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d transposition array.\n",m);
- return(MEMORY_ERROR);
- }
- }
- for(m=1;n<strmcnt*4;n++,m++) { // Times in envtable where envdata read, for each-event-in-each-stream
- if((dz->parray[n] = (double *)malloc(eventcnt * sizeof(double)))==NULL) { // NB these could have been randomised
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d envelope readtime array.\n",m);
- return(MEMORY_ERROR);
- }
- }
- for(m=1;n<strmcnt*5;n++,m++) { // Stacking values for each-event-in-each-stream
- if((dz->parray[n] = (double *)malloc(eventcnt * sizeof(double)))==NULL) { // NB these could have been randomised
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d envelope readtime array.\n",m);
- return(MEMORY_ERROR);
- }
- }
- if((dz->parray[n++] = (double *)malloc(strmcnt * sizeof(double)))==NULL) { // Stream level at leftmost channel
- sprintf(errstr,"INSUFFICIENT MEMORY for left-levels array.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[n++] = (double *)malloc(strmcnt * sizeof(double)))==NULL) { // Stream level at rightmost channel
- sprintf(errstr,"INSUFFICIENT MEMORY for right-levels array.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[n++] = (double *)malloc(strmcnt * sizeof(double)))==NULL) { // Positioning of output streams
- sprintf(errstr,"INSUFFICIENT MEMORY for storing input envelope data.\n");
- return(MEMORY_ERROR);
- }
- dz->envbuf = n; // Store array number of temporary envelope
- if((dz->parray[n++] = (double *)malloc(14 * sizeof(double)))==NULL) { // Stores temporary envelope calculated for specific event
- sprintf(errstr,"INSUFFICIENT MEMORY for current envelope array.\n");
- return(MEMORY_ERROR);
- }
- dz->envsrcs = n; // Store array number of input envelope data
- if((dz->parray[n++] = (double *)malloc((dz->envcount * 15) * sizeof(double)))==NULL) { // Original envelope data in blocks of time+14 = 15
- sprintf(errstr,"INSUFFICIENT MEMORY for storing input envelope data.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[n++] = (double *)malloc(strmcnt * sizeof(double)))==NULL) { // Centre of envelope (for stacking)
- sprintf(errstr,"INSUFFICIENT MEMORY for storing input envelope data.\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[n++] = (double *)malloc(eventcnt * sizeof(double)))==NULL) { // Group-time of events
- sprintf(errstr,"INSUFFICIENT MEMORY for storing input envelope data.\n");
- return(MEMORY_ERROR);
- }
- if(dz->mode > 0) { // Channel levels in calculation of multichannel output
- dz->outlevs = n;
- if((dz->parray[n] = (double *)malloc(dz->iparam[FRAC_CHANS] * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to store out-levels for multichannel output.\n");
- return(MEMORY_ERROR);
- }
- }
- /*
- * INTEGER ARRAYS: S = number of streams
- *
- * lmost
- * | rmost
- * | | |
- * address 0 1 |
- * | | |
- * array S S |
- * length | | |
- */
- if((dz->iparray = (int **)malloc(2 * sizeof(int *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for integer arrays.\n");
- return(MEMORY_ERROR);
- }
- if((dz->iparray[0] = (int *)malloc(strmcnt * sizeof(int)))==NULL) { // leftmost channel for each stream
- sprintf(errstr,"INSUFFICIENT MEMORY for stream leftmost channels.\n");
- return(MEMORY_ERROR);
- }
- if((dz->iparray[1] = (int *)malloc(strmcnt * sizeof(int)))==NULL) { // rightmost channel for each stream
- sprintf(errstr,"INSUFFICIENT MEMORY for stream rightmost channels.\n");
- return(MEMORY_ERROR);
- }
- /*
- * LONG ARRAYS: S = number of streams iptr (start of read WITHIN current input buffer, for each stream)
- * | temp storage of event starttimes
- * |---------------|---------------| | |
- * | segendsamp | inreadsamp | | | NB segendsamp is in MONO samps
- * address 0 S 2S| | need to change to (segendsamp * chans)
- * | | | 2S+1 + lmost(rmost) % dz->buflen
- * array | maxevents | maxevents | | | for write!!
- * length | | strmcnt
- * | | | strmcnt
- */
- if((dz->lparray = (int **)malloc(((strmcnt*2)+2) * sizeof(int *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for ints arrays.\n");
- return(MEMORY_ERROR);
- }
- for(n=0,m=1;n<strmcnt;n++,m++) { // End sample for each-event-in-each-stream, counted in MONO
- if((dz->lparray[n] = (int *)malloc(eventcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d eventend sampletimes.\n",m);
- return(MEMORY_ERROR);
- }
- }
- for(m=1;n<strmcnt*2;n++,m++) { // Startsample in source for each-event-in-each-stream
- if((dz->lparray[n] = (int *)malloc(eventcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream %d eventread sampletimes.\n",m);
- return(MEMORY_ERROR);
- }
- } // Pointers within CURRENT buffer, to start of segments to read, for each stream
- if((dz->lparray[n++] = (int *)malloc(strmcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream src Pointers in input buffers.\n");
- return(MEMORY_ERROR);
- } // Temporary storage of event start-times for each stream
- if((dz->lparray[n] = (int *)malloc(strmcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for stream src Pointers in input buffers.\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = read_the_special_data(dz))<0) // Read the envelope data input
- return exit_status;
- // Assign output streams to correct positions among output channels
-
- lmost = dz->iparray[0];
- rmost = dz->iparray[1];
- llev = dz->parray[strmcnt * 5];
- rlev = dz->parray[(strmcnt * 5) + 1];
- pos = dz->parray[(strmcnt * 5) + 2];
- if(strmcnt == chans) {
- for(n = 0;n<chans;n++) {
- lmost[n] = n;
- rmost[n] = (lmost[n] + 1) % chans;
- llev[n] = 1.0;
- rlev[n] = 0.0;
- }
- } else {
- if((dz->mode == 0 && dz->vflag[1]) || chans == 2) {
- for(n = 0;n<strmcnt;n++) {
- pos[n] = ((chans - 1) * n)/(double)(strmcnt - 1);
- lmost[n] = (int)floor(pos[n]);
- pos[n] -= lmost[n];
- }
- } else {
- for(n = 0;n<strmcnt;n++) {
- pos[n] = (chans * n)/(double)strmcnt;
- lmost[n] = (int)floor(pos[n]);
- pos[n] -= lmost[n];
- }
- }
- for(n = 0;n<strmcnt;n++) {
- rmost[n] = (lmost[n] + 1) % chans;
- if(flteq(pos[n],0.0)) {
- rlev[n] = 0.0;
- llev[n] = 1.0; // pos values overwritten by associated level values (ETC below)
- } else if(flteq(pos[n],1.0)) {
- rlev[n] = 1.0;
- llev[n] = 0.0;
- } else {
- pos[n] *= 2.0;
- pos[n] -= 1.0; // Change position to -1 to +1 range
- pancalc(pos[n],&leftgain,&rightgain);
- rlev[n] = rightgain;
- llev[n] = leftgain;
- }
- }
- }
- if(dz->mode > 0) {
- // SET UP FILTER
- if((exit_status = setup_lphp_filter(dz))<0) // Set up the distance filter
- return exit_status;
- }
- return FINISHED;
- }
- /**************************** CREATE_FRACTURE_SNDBUFS ****************************/
- int create_fracture_sndbufs(int maxpulse,double maxtrans,int minfragmax,int *ibuflen,int *envbuflen,int *overflow, int *mbuflen, dataptr dz)
- {
- int framesize = dz->infile->channels * F_SECSIZE;
- int chans;
- unsigned int bigbufsize;
- int seccnt, obuflen, fbuflen = 0;
- double d_obuflen;
- if(dz->mode == 0)
- chans = dz->iparam[FRAC_CHANS];
- else
- chans = STEREO;
- if((dz->sampbuf = (float **)malloc(sizeof(float *) * 8))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
- return(MEMORY_ERROR);
- }
- if((dz->sbufptr = (float **)malloc(sizeof(float *) * 8))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
- return(MEMORY_ERROR);
- }
- *ibuflen = maxpulse; // Already allows for maximum random expansion of maximum read-segment length
- *ibuflen *= 3; // Allow for maximum offset of reads in different streams
- *ibuflen += minfragmax; // Allows for minimum fragment-size being larger than maxpulse
- *ibuflen += 64; // SAFETY
- seccnt = *ibuflen/framesize;
- if(seccnt * framesize != *ibuflen) {
- seccnt++;
- *ibuflen = seccnt * framesize;
- }
- *envbuflen = maxpulse * 2; // Frag start and ends can be randomly displaced away from one another ... allow a maximum safety margin!!
- *envbuflen += minfragmax; // If a minimum fragment-size specified, allows for length of minsize + any rand-extension
- *envbuflen += 16; // SAFETY
- seccnt = (*envbuflen)/framesize;
- if(seccnt * framesize != *envbuflen) {
- seccnt++;
- *envbuflen = seccnt * framesize;
- }
- d_obuflen = (double)maxpulse;
- if(maxtrans > 1.0) // Allow for maximum transposition (downwards) of data (redundant: transpos always upwards)
- d_obuflen *= maxtrans;
- obuflen = (int)ceil(d_obuflen) + 16; // SAFETY
- obuflen *= chans;
- seccnt = obuflen/framesize;
- if(seccnt * framesize != obuflen) {
- seccnt++;
- obuflen = seccnt * framesize;
- }
- if(dz->mode > 0) {
- *mbuflen = (obuflen/STEREO) * dz->iparam[FRAC_CHANS];
- fbuflen = obuflen;
- }
- *overflow = obuflen * 2; // Allow for 2 whole maximal segments overwrite of end of output buffer
- *overflow += minfragmax; // Allow for min-length segments which are bigger than maxpulse
- dz->buflen = obuflen;
- bigbufsize = *ibuflen + (*envbuflen * 2) + obuflen + *overflow + fbuflen + *mbuflen;
- if((dz->bigbuf = (float *)malloc(bigbufsize * sizeof(float))) == NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
- return(MEMORY_ERROR);
- }
- /*
- * SOUND BUFFERS
- *
- * MODE 1 | input | enveloping| stacking | output | overflow |
- *
- * MODE 2 | input | enveloping| stacking | stereo | stereo | filter | multichan |
- * output overflow buffer output
- */
- dz->sampbuf[0] = dz->bigbuf;
- dz->sbufptr[0] = dz->sampbuf[0];
- dz->sampbuf[1] = dz->sampbuf[0] + *ibuflen;
- dz->sbufptr[1] = dz->sampbuf[1];
- dz->sampbuf[2] = dz->sampbuf[1] + *envbuflen;
- dz->sbufptr[2] = dz->sampbuf[2];
- dz->sampbuf[3] = dz->sampbuf[2] + *envbuflen;
- dz->sbufptr[3] = dz->sampbuf[3];
- dz->sampbuf[4] = dz->sampbuf[3] + obuflen;
- dz->sbufptr[4] = dz->sampbuf[4];
- dz->sampbuf[5] = dz->sampbuf[4] + *overflow;
- dz->sbufptr[5] = dz->sampbuf[5];
- dz->sampbuf[6] = dz->sampbuf[5] + fbuflen;
- dz->sbufptr[6] = dz->sampbuf[6];
- dz->sampbuf[7] = dz->sampbuf[6] + *mbuflen;
- dz->sbufptr[7] = dz->sampbuf[7];
- return FINISHED;
- }
- /**************************** READ_THE_ENVELOPE ****************************/
- int read_the_envelope(double now, dataptr dz)
- {
- double *envarray = dz->parray[dz->envsrcs], *tempenv = dz->parray[dz->envbuf];
- int n, m, k, thisenv, lastenv, lastj, thisj, endj;
- double time_of_envelope, lasttime, thistime, timediff, timefrac, val;
- for(n = 0,m= 0;m < dz->envcount; n+=15,m++) { // Step through the time values, at every 15th entry
- time_of_envelope = envarray[n];
- if(time_of_envelope >= now) { // Once time-of-envelope is beyond "now" time
- thisenv = m; // Mark the two envelopes bracketing "now"
- lastenv = m-1;
- if(lastenv < 0) { // If there is no previous envelope, we must be at zero time
- for(k=0;k<14;k++) // so copy envelope at zero time to output (temporary envelope)
- tempenv[k] = envarray[k+1];
- return FINISHED;
- } else { // Otherwise, get the array-indexes of the times of the bracketing envelopes
- lastj = lastenv * 15;
- thisj = thisenv * 15;
- endj = thisj; // And remember the index of the END of the last-envelope data
- lasttime = envarray[lastj]; // get those bracketing times
- thistime = envarray[thisj]; // and calculate the fraction of time we are at, between the bracketing times
- timediff = thistime - lasttime;
- timefrac = (now - lasttime)/timediff;
- lastj++; // Step from time-of-envelope to envelope data itself
- thisj++;
- k = 0; // Initialise counter for output temporary-envelope
- while(lastj < endj) { // For every (time and level) entry in the bracketing envelopes
- val = envarray[thisj] - envarray[lastj];
- val *= timefrac; // Interpolate using timefrac
- val += envarray[lastj];
- tempenv[k++] = val;
- lastj++;
- thisj++;
- }
- return FINISHED;
- }
- }
- } // If we've gone through all data without reaching input "time", use final envelope
- lastenv = m-1;
- lastj = lastenv * 15;
- lastj++;
- for(k=0;k<14;k++)
- tempenv[k] = envarray[lastj++];
- return FINISHED;
- }
- /**************************** GETSTAKCENTRE ****************************
- *
- * Find time of (first) peak in envelope
- */
- double getstakcentre(double *tempenv,dataptr dz)
- {
- int tim, lev;
- double maxlev = -1.0;
- double maxtim = 0.0;
- for(tim=0,lev=1;tim < 14;tim+=2,lev+=2) {
- if(tempenv[lev] > maxlev) {
- maxlev = tempenv[lev];
- maxtim = tempenv[tim];
- }
- }
- return maxtim;
- }
- /**************************** GETSTAKWRITESTT ****************************
- *
- * Find sample in stak-buffer where transposed-data, centred on peak, should start to be written
- */
- int getstakwritestt(double stakcntr,int ldur,double incr)
- {
- double stakcentre = (double)ldur * stakcntr;
- double shrinkto = stakcentre/incr;
- return (int)round(stakcentre - shrinkto);
- }
- /************************************ 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;
- }
- }
- }
- /*************************** PANSPREAD ****************************
- *
- * This function takes the output of mode 0 (but forced to stereo)
- * and uses it as the stereo input to the multichannel spatialiseation process (of "mchanpan" - MODE 3- stereo input branch)
- *
- * Data is fed in in chunks of dz->buflen (or possibly less for the last chunk)
- * and written to multichannel output from here.
- *
- * There is no reason to run this part of the function during the level-testing pass
- * as, once the stereo level has been normalised, there is no (per channel) level increase at this stage.
- *
- * Signal gain has several componenets
- * Stereo positioning gain (relative level on Left/Right loudspeakers) is already included in the input stereo signal
- * Position gain perpendicular to stereo-plain OR attenuation with distance beyond the circle
- * Natural attenuation of the image "atten" where it fades before reaching infinity.
- * Externally imposed gain-reduction "gain" to avoid an overload.
- */
- int panspread(int *sectcnt,double *centre,double *spread,int *cntrswitch,int *outside,double *fmix,int samps_to_process,dataptr dz)
- {
- int exit_status, pan_exit_status = CONTINUE, outchans = dz->iparam[FRAC_CHANS], m, k;
- int ibufpos, obufpos = 0;
- double *levels;
- int inchans = STEREO;
- float *ibuf = dz->sampbuf[3]; // Input buffer is the former "obuf", now used as intermediate stereo-storage
- float *fbuf = dz->sampbuf[5]; // buffer for filtering
- float *obuf = dz->sampbuf[6]; // and the output buffer is the multichan-outbuf "mbuf"
-
- double time = 0.0, srate = (double)dz->infile->srate, gain = dz->param[FRAC_GAIN];
- int obuflen = (dz->buflen/STEREO) * outchans;
- double stereo_pos, atten, timeratio;
- double relpos, temp, holecompensate;
- double left_leftchan_level, left_ritechan_level;
- double valcentre, valoffcen;
- double fadeoutat = dz->fulldur - dz->param[FRAC_DN];
- int halfstage = outchans/2;
- int c_left, c_rite, cen_tr;
- double left_contrib_to_c_left, rite_contrib_to_c_left, left_contrib_to_c_rite, rite_contrib_to_c_rite, val;
- levels = dz->parray[dz->outlevs]; // Array created earlier.
- memset((char *)obuf,0,obuflen * sizeof(float));
- if(dz->param[FRAC_DN] <= 0.0)
- fadeoutat = dz->fulldur * 200.0; // i.e. an unreachable time
- for(ibufpos = 0, obufpos = 0;ibufpos < samps_to_process;ibufpos+=inchans,obufpos += outchans) {
- if((*sectcnt) % 256 == 0) {
- time = (double)(*sectcnt)/srate;
- if((exit_status = read_values_from_all_existing_brktables(time,dz))<0)
- return(exit_status);
- if(spread_pan(centre,cntrswitch,outside,spread,fmix,dz) == FINISHED) {
- pan_exit_status = FINISHED;
- break;
- }
- }
- if(time < dz->param[FRAC_UP]) { // Factor in any natural decay of event (i.e NOT distance realted)
- timeratio = time/dz->param[FRAC_UP];
- atten = pow(timeratio,dz->param[FRAC_ATTEN]);
- } else if(time > fadeoutat) {
- timeratio = (time - fadeoutat)/dz->param[FRAC_DN];
- timeratio = 1.0 - timeratio;
- atten = pow(timeratio,dz->param[FRAC_ATTEN]);
- } else
- atten = 1.0;
- atten *= gain; // Factor in any externally imposed gain-limiting.
- if(*outside) {
- stereo_pos = 1.0 - *spread; // Spread is to left of centre, incresing leftward, but stereo-position measured rightward
- relpos = fabs(0.5 - stereo_pos) * 2.0; // position relative_to_stereo_centre : Range 0-1 goes to 1-0-1
- temp = 1.0 + (relpos * relpos); // calculate stereo-hole-in-middle compensation
- holecompensate = ROOT2 / sqrt(temp);
- left_leftchan_level = *spread * levels[0] * holecompensate; // contrib of left chan to left edge of shrunk image
- left_ritechan_level = (1-(*spread)) * levels[0] * holecompensate; // contrib of right chan to left edge of shrunk image
- // ADD IN ANY FILTERED SOUND, TO STEREO IMAGE
- if(*fmix > 0) {
- ibuf[ibufpos] = (float)(((1-(*fmix)) * ibuf[ibufpos]) + (*fmix * fbuf[ibufpos]));
- ibuf[ibufpos+1] = (float)(((1-(*fmix)) * ibuf[ibufpos+1]) + (*fmix * fbuf[ibufpos+1]));
- }
- if(*cntrswitch == 0) {
- valcentre = ibuf[ibufpos+1]; // The RHS of stereo will remain where it is
- valoffcen = ibuf[ibufpos]; // The LHS will drift towards the right, till they become mono, at right (=final image centre)
- } else {
- valcentre = ibuf[ibufpos]; // LHS & RHS of original stereo signal switched, because centre moved to opposite pole: see elsewhere
- valoffcen = ibuf[ibufpos+1];
- }
- valcentre = valcentre + (left_ritechan_level * valoffcen); // Stereo-right + an increasing portion of stereo-left
- valoffcen = left_leftchan_level * valoffcen; // a decreasing portion of stereo left
- cen_tr = (int)floor(*centre);
- c_left = cen_tr - 1;
- if(c_left < 0)
- c_left += outchans;
- obuf[obufpos + cen_tr] = (float)(valcentre * atten * levels[0]); // Attenuation is any dying away of signal proper (nothing to do with distance)
- obuf[obufpos + c_left] = (float)(valoffcen * atten * levels[0]); // levels[0] is the level associated with distance from circle
- } else {
- c_left = (int)floor(*centre);
- c_rite = c_left + 1;
- if(c_rite >= outchans)
- c_rite -= outchans;
- for(k=1;k<halfstage;k++) { // All loudpseakers to left of central pair get left signal (unless reading from opp. centre : cntrswitch = 1)
- m = c_left - k; // Values in "levels" decide how much of the signal is played
- if(m < 0)
- m += outchans;
- if(*cntrswitch)
- obuf[obufpos + m] = (float)(ibuf[ibufpos+1] * levels[m] * atten);
- else
- obuf[obufpos + m] = (float)(ibuf[ibufpos] * levels[m] * atten);
- }
- for(k=1;k<halfstage;k++) { // All loudpseakers to right of central pair get right signal (unless etc.)
- m = c_rite + k;
- if(m >= outchans)
- m -= outchans;
- if(*cntrswitch)
- obuf[obufpos + m] = (float)(ibuf[ibufpos] * levels[m] * atten);
- else
- obuf[obufpos + m] = (float)(ibuf[ibufpos+1] * levels[m] * atten);
- } // Central pair get a mix of left and right signals
- stereo_pos = *centre - (double)c_left;
- left_contrib_to_c_left = (1.0 + (2.0 * stereo_pos))/2.0;
- left_contrib_to_c_left = min(1.0,left_contrib_to_c_left);
- rite_contrib_to_c_left = (1.0 - (2.0 * stereo_pos))/2.0;
- rite_contrib_to_c_left = max(0.0,rite_contrib_to_c_left);
- if(*cntrswitch)
- val = (ibuf[ibufpos+1] * left_contrib_to_c_left) + (ibuf[ibufpos] * rite_contrib_to_c_left);
- else
- val = (ibuf[ibufpos] * left_contrib_to_c_left) + (ibuf[ibufpos+1] * rite_contrib_to_c_left);
- val *= levels[c_left];
- obuf[obufpos + c_left] = (float)(val * atten);
- left_contrib_to_c_rite = ((2.0 * stereo_pos) - 1.0)/2.0;
- left_contrib_to_c_rite = max(0.0,left_contrib_to_c_rite);
- rite_contrib_to_c_rite = (3.0 - (2.0 * stereo_pos))/2.0;
- rite_contrib_to_c_rite = min(1.0,rite_contrib_to_c_rite);
- if(*cntrswitch)
- val = (ibuf[ibufpos+1] * left_contrib_to_c_rite) + (ibuf[ibufpos] * rite_contrib_to_c_rite);
- else
- val = (ibuf[ibufpos] * left_contrib_to_c_rite) + (ibuf[ibufpos+1] * rite_contrib_to_c_rite);
- val *= levels[c_rite];
- obuf[obufpos + c_rite] = (float)(val * atten);
- left_contrib_to_c_rite = ((2.0 * stereo_pos) - 1.0)/2.0;
- }
- (*sectcnt)++;
- }
- if(obufpos > 0) {
- if((exit_status = write_samps(obuf,obufpos,dz))<0)
- return(exit_status);
- }
- return pan_exit_status;
- }
- /* WITH CENTRE BETWEEN CHANNELS ...
- * left_contrib_to_c_left = * rite_contrib_to_c_left = * left_contrib_to_c_rite = * rite_contrib_to_c_rite =
- * MAX of 1.0 AND * MIN of 0.0 AND * MAX of 0.0 AND * MAX of 1.0 AND
- * (1.0 + (2.0 * stereo_pos)/2.0; * (1.0 - (2.0 * stereo_pos)/2.0; * ((2.0 * stereo_pos) - 1.0)/2.0; * (3.0 - (2.0 * stereo_pos)/2.0;
- * * * *
- * POSITION OF CENTRE * POSITION OF CENTRE * POSITION OF CENTRE * POSITION OF CENTRE
- * c-left c_rite * c-left c_rite * c-left c_rite * c-left c_rite
- * 1.0 | . . . .________| * 1.0 |. . . . . . . . | * 1.0 | . . . . . . . .| * 1.0 |________ . . . |
- * | / | * | | * | | * | \ |
- * | / | * | | * | | * | \ |
- * | / | * | | * | | * | \ |
- * 0.5 |/ . . . . . . . | * 0.5 |. . . . . . . . | * 0.5 |. . . . . . . . | * 0.5 |. . . . . . . .\|
- * | | * |\ | * | /| * | |
- * | | * | \ | * | / | * | |
- * | | * | \ | * | / | * | |
- * 0.0 | . . . . . . . | * 0.0 | . . \_________| * 0.0 |_________/ . . | * 0.0 | . . . . . . . .|
- *
- */
- /*************************** SPREAD_PAN ****************************/
- int spread_pan(double *thiscentre,int *cntrswitch,int *outside,double *spread,double *fmix,dataptr dz)
- {
- int outchans = dz->iparam[FRAC_CHANS];
- double centre = (double)dz->iparam[FRAC_CENTRE];
- double halfspread = 0.0, front = dz->param[FRAC_FRONT], ffront;
- double depth;
- double rolloff = dz->param[FRAC_ROLLOFF];
- double *levels = dz->parray[dz->outlevs];
- double spredej_left, spredej_right;
- int spredej_left_leftchan, spredej_left_rightchan, spredej_right_leftchan, spredej_right_rightchan, k, j, ochan;
- double range, maxlevel, hole, stereopos_left, stereopos_right, relpos, temp, holecompensate;
- double holej_right, holej_left, zleft, zright, floor_zleft, floor_zright;
- double left_leftchan_level, right_rightchan_level;
- double kk, jj, holing, mingap;
- double contraction_distance, filter_distance;
- *cntrswitch = 0;
- *outside = 0;
- depth = (dz->param[FRAC_MDEPTH] * outchans)/2.0; // Find (max) no of outchans to turn on
- depth = min(depth,(double)outchans/2.0); // depth (no of ON lspks) to each side of centre is 1/2 of this
- if((centre = centre - 1.0) < 0.0) // Change from 1-to-N to 0-to-(N-1) frame, for calculations
- centre += (double)outchans;
- if(fabs(front) <= 1.0) { // If WITHIN the circle of lspkrs
- centre -= 0.5; // force the active centre to be BETWEEN 2 channels
- if(centre < 0.0)
- centre += outchans;
- if(front >= 0) // Front moves from a spread of 1 lspkr-width (at 1)
- *spread = (1-front) * (outchans/2 - 1) + 1; // to a spread of 1/2-of-lspkrs (outchans/2) at midline
- else {
- front = -front; // After midline, hole in lspkrs has same relation to (abs value of) front.
- *spread = (1-front) * (outchans/2 - 1) + 1; // so calculate symmetrically
- *spread = outchans - *spread; // then subtract hole from total lspkrs
- }
- } else { // Leading-edge of front is outside circle of lspkrs
- *outside = 1;
- if(front < -1) { // If passed OUT of ring, place front at its TRAILING edge, for calculations
- front += (dz->param[FRAC_MDEPTH] * 2);
- if(front <= -2) // Once trailing edge of data reaches infinity, curtail output
- return FINISHED;
- else if(front >= -1) { // If trailing edge of front has (unlike true front) NOT left circle of lspkrs
- centre -= 0.5; // force the active centre to be BETWEEN 2 channels
- if(centre < 0.0)
- centre += outchans;
- *outside = 0; // Do normal inside-circle calculations BUT
- centre -= (double)(outchans/2); // Invert frame of reference
- if(centre < 0.0) // centre -> leaving-centre opposite original centre
- centre += (double)outchans;
- front = -front; // Front inverted symmetrically about centre-line (0)
- *cntrswitch = 1; // and left and right inverted in calling loop
- if(front >= 0) // Then calculate spread in normal way, but from this leaving-centre
- *spread = (1-front) * (outchans/2 - 1) + 1;
- else {
- front = -front;
- *spread = (1-front) * (outchans/2 - 1) + 1;
- *spread = outchans - *spread;
- } // As depth MUST now be covering all chans from trailing edge (new "front") to leaving-centre
- depth = (*spread)/2.0; // set depth to real halfspread,
- }
- }
- if(*outside) { // Once front OUTSIDE circle, shrink to MONO into the original-specified central channel
- ffront = fabs(front); // Calculations for outside ring are symmetrical (Range 1 to 2)
- ffront -= 1.0; // Change range to 0-1 : ringedge-to-infinity (Range 0 to 1)
- maxlevel = pow((1.0 - ffront),dz->param[FRAC_ATTEN]); // As front increases, loudness decreases
- // (and only 1channel active, so no scaling required for no. of chans
- contraction_distance = min(1.0,ffront/dz->param[FRAC_ZPOINT]); // Fraction of distance towards zero-angle point, max 1.0
- *spread = pow((1.0 - contraction_distance),dz->param[FRAC_CONTRACT]);// As contraction_distance increases, width decreases
- halfspread = (*spread)/2.0;
- filter_distance = min(1.0,ffront/dz->param[FRAC_FPOINT]); // Fraction of distance towards total-filering point, max 1.0
- *fmix = pow(filter_distance,dz->param[FRAC_FFACTOR]); // As filter_distance increases, proportion filtered sig in mix increases
- centre = (double)dz->iparam[FRAC_CENTRE]; // Revert to original channel-centred centre
- if((centre = centre - 1.0) < 0.0) // Change from 1-to-N to 0-to-(N-1) frame, for calculations
- centre += outchans;
- if(front < 0.0) { // If LEAVING circle,
- *cntrswitch = 1; // Invert left and right in calling loop
- centre += outchans/2; // Invert centre, to opposite-to-centre channel
- if(centre > outchans)
- centre -= outchans;
- }
- for(ochan = 0;ochan < outchans;ochan++)
- levels[ochan] = 0.0;
- levels[0] = maxlevel; // Central channel to which we'll shrink gets current maxlevel, but we canstore it in levels[0]
- *thiscentre = centre;
- return(CONTINUE); // we're returning an "outside" flag, a moved centre, a shrunk "halfspread" and a filtering-mix value
- }
- }
- halfspread = (*spread)/2.0;
- if(depth <= 0.0)
- depth = FLTERR;
-
- if((halfspread = (*spread)/2.0) == 0.0)
- halfspread = FLTERR;
- for(ochan = 0;ochan < outchans;ochan++)
- levels[ochan] = 0.0;
- /* Establish maxlevel (determined by rolloff) */
- if(*spread < 1.0)
- range = 0.0;
- else
- range = 1.0 - (1.0/(*spread));
- maxlevel = 1.0 - (rolloff * range);
- // Set all channels fully within the spread to maxlevel
-
- spredej_left = centre - halfspread; // spredej_left and right could be determined
- while(spredej_left < 0) // by a "position-of-front" parameter
- spredej_left += (double)outchans; // working backwards towards centre, using halfspread
- spredej_right = centre + halfspread;
- while(spredej_right >= outchans) // Once this is done .. easier to deal with
- spredej_right -= (double)outchans; // distant (filtered) signalwith no (or limited) width
- spredej_left_leftchan = (int)floor(spredej_left); // at trailing, or leading centre
- if((spredej_left_rightchan = spredej_left_leftchan + 1) >= outchans)
- spredej_left_rightchan = 0; // Centre is behind front if front moving away from entre
- spredej_right_leftchan = (int)floor(spredej_right); // and <= hlafway to f/b midoint.
- // Having crossed that, centre moves to OPPOSITE position.
- hole = *spread - (depth * 2.0); // Once available lspk-spread is < specified spread,
- // there.s no hole in the middle.
- if(*spread >= outchans) { // Once available loudspeaker spread < 2
- for(k = 0;k<outchans; k++) // spread determined articially by how we deal with
- levels[k] = maxlevel; // distance (beyond octagon) effect, and how we filter
- if(hole <= 0.0) // as we shrink the stereo width.
- return CONTINUE;
- } else if(*spread > 1.0) {
- k = spredej_left_leftchan;
- if(spredej_left_leftchan == spredej_left)
- levels[k] = maxlevel;
- if(++k >= outchans)
- k -= outchans;
- while(k != spredej_right_leftchan) {
- levels[k] = maxlevel;
- if(++k >= outchans)
- k -= outchans;
- }
- levels[spredej_right_leftchan] = maxlevel;
- } else { // In fact, this is what is happening here !!!!
- /* Deal with case where spread extends to both sides of a channel, even if less than 1.0 */
-
- zleft = centre - halfspread;
- zright = centre + halfspread;
- if(zleft < 0.0) {
- zleft += outchans;
- zright += outchans;
- }
- if(zleft >= 0.0)
- floor_zleft = floor(zleft);
- else
- floor_zleft = -ceil(fabs(zleft));
- if(zright >= 0.0)
- floor_zright = floor(zright);
- else
- floor_zright = -ceil(fabs(zright));
- if(floor_zleft < floor_zright)
- levels[spredej_right_leftchan] = maxlevel;
- }
- /* Do fractional channels on leading edges of spread */
- stereopos_left = spredej_left - (double)spredej_left_leftchan;
- relpos = fabs(0.5 - stereopos_left) * 2.0; // position relative_to_stereo_centre : Range 0 - 1
- temp = 1.0 + (relpos * relpos); // calculate stereo-hole-in-middle compensation
- holecompensate = ROOT2 / sqrt(temp);
- left_leftchan_level = (1 - stereopos_left) * maxlevel * holecompensate;
- if(spredej_left_leftchan != spredej_right_leftchan)
- levels[spredej_left_leftchan] = left_leftchan_level;
- stereopos_right = spredej_right - (double)spredej_right_leftchan;
- relpos = fabs(0.5 - stereopos_right) * 2.0; // position relative_to_stereo_centre : Range 0 - 1
- temp = 1.0 + (relpos * relpos); // calculate stereo-hole-in-middle compensation
- holecompensate = ROOT2 / sqrt(temp);
- right_rightchan_level = stereopos_right * maxlevel * holecompensate;
- if(spredej_right > spredej_right_leftchan) {
- if((spredej_right_rightchan = spredej_right_leftchan + 1) >= outchans)
- spredej_right_rightchan -= outchans;
- if(spredej_right_rightchan != spredej_left_rightchan) {
- if(spredej_right_rightchan == spredej_left_leftchan) {
- levels[spredej_right_rightchan] += right_rightchan_level;
- } else {
- levels[spredej_right_rightchan] = right_rightchan_level;
- }
- }
- }
- /* IF hole in the middle of the spread, because depth too small, find edges of hole */
- halfspread = (*spread)/2.0;
- if(hole > 0.0) {
- holej_right = centre + halfspread - depth;
- holej_left = centre - halfspread + depth;
- k = (int)ceil(holej_left);
- j = (int)floor(holej_right); // Look at all chans in hole
- while(k <= j) {
- kk = k - holej_left;
- jj = holej_right - k;
- mingap = min(jj,kk);
- holing = min(mingap,1.0);
- holing = 1.0 - holing;
- ochan = k;
- while(ochan < 0)
- ochan += outchans;
- while(ochan >= outchans)
- ochan -= outchans;
- levels[ochan] *= holing;
- k++;
- }
- }
- *thiscentre = centre;
- return CONTINUE;
- }
- /*
- * INNER HOLE
- * range = Starts at 1.0 , where no hole. Ends at appropriate stereo-position-level (this_level), once hole extends as far as an existing chan;
- * mingap = minimum distance from holeedge to nearest channel
- * mingap += hole; we then add this to size of hole, to see size of area including hole and distance to nearest chan. Always <= 1.0;
- * holeratio = hole/mingap; with a tiny hole, this is always c. zero, as hole enlarges, gets bigger, till, when hole touches a channel, it gets to be 1.0
- * this_level = 1.0 - (range * holeratio); When holeratio = 1, level becomes 1.0 - range = this_level i.e. expected stereo level
- * = 1.0 - (1.0 - this_level) = this_level i.e. expected stereo level
- */
- /*
- * POSITIONS OF MOVING FRONT
- * 2 = "+infinitely" distant: 1 = in plane of front-centre lspkr : 0 = in plane of midline:
- * -1 = in plane of read lspkr: -2 = "-infinitely" distant
- *
- * Depth-param now expressed as fraction of lspkr-space. 1 = chans, 1/2 = chans/2 etc ..... (so original spread param = depth *chans)
- *
- * 2 Let "spread" at 1 be 1/chans (i.e. 1/2 lspkr width on either side of central lspkr)
- * "spread" at centre (front = 0) is always ochans/2
- * 1 For "front" in range 1 - 0 therefore.
- * x x spread = ((1 - front) * (chans/2 - 1)) + 1 and calculations can proceed as normal
- * For front in range 0 to -1,by symmetry
- * x 0 x spread = chans - (((1 + front) * (chans/2 - 1)) + 1)
- *
- * x x As the front has a depth, and therefore a trailing edge which does not reach -1 at same time as true front,
- * -1 calculations relating to fade-out and filtering between -1 and -2, have to be based on trailing edge vals.
- * So trailing edge only reaches -2 when front is at -2+depth.
- * User needs to build this in to the "fonr" breakpoint file data.
- * -2
- * With the new value of depth, trailing edge is at front + (depth * 2)
- * This is "+" as front always move +ve to -ve
- * and uses factor "2" because, when depth 1 = all lspkrs in use, but distance front to back (1 to -1) = 2.
- * So if 1/2 loudpseakers are activated, trailing edge is half-way back round space and:
- * and "HALFway" for front means distance of "1" (Thus depth[1/2] * 2 = 1)
- */
- //FILTER
- // set stopfrq [expr $sd(filt) + (double($sd(filt))/4.0)]
- // set cmd [file join $evv(CDPROGRAM_DIR) filter]
- // set cmd [list $cmd lohi 1 $sd_infnam cdptest0$evv(SNDFILE_EXT) -96 $sd(filt) $stopfrq]
- /****************************** FILTER_PROCESS *************************/
- int filter_process(int *samps_to_process,int *endzeros,dataptr dz)
- {
- int exit_status;
- float *fbuf = dz->sampbuf[5], *obuf = dz->sampbuf[3];
- int n;
- memset((char *)fbuf,0,dz->buflen * sizeof(float));
- if(*samps_to_process)
- memcpy((char *)fbuf,(char *)obuf,*samps_to_process * sizeof(float));
- dz->ssampsread = dz->buflen; // To force filter to continue to operate, when input exhausted
- if((exit_status = do_lphp_filter_stereo(dz)) <0)
- return(exit_status);
- if( *samps_to_process == 0) {
- n = dz->buflen - 1;
- while(n >= 0) { // Force exit when 256 consecutive grp-samples are zero
- if(fbuf[n] == 0.0)
- (*endzeros)++;
- else
- break;
- n--;
- }
- n++;
- if(*endzeros >= 256 * STEREO) {
- *samps_to_process = n;
- return FINISHED;
- }
- }
- return(CONTINUE);
- }
- /***************************** FILTER *************************************/
- int do_lphp_filter_stereo(dataptr dz)
- {
- int exit_status, i;
- int index, fbase = dz->outlevs + 1;
-
- double *e1,*e2,*s1,*s2;
-
- double *den1 = dz->parray[fbase + FLT_DEN1];
- double *den2 = dz->parray[fbase + FLT_DEN2];
- double *cn = dz->parray[fbase + FLT_CN];
- for(i=0; i < STEREO; i++) {
- index = i * FLT_LPHP_ARRAYS_PER_FILTER;
-
- e1 = dz->parray[fbase + FLT_E1_BASE + index];
- e2 = dz->parray[fbase + FLT_E2_BASE + index];
- s1 = dz->parray[fbase + FLT_S1_BASE + index];
- s2 = dz->parray[fbase + FLT_S2_BASE + index];
- if((exit_status = lphp_filt_stereo(e1,e2,s1,s2,den1,den2,cn,dz,i))<0)
- return exit_status;
- }
- return(FINISHED);
- }
- /***************************** LPHP_FILT_CHAN *************************************/
- int lphp_filt_stereo(double *e1,double *e2,double *s1,double *s2,
- double *den1,double *den2,double *cn,dataptr dz,int chan)
- {
- int i;
- int k;
- float *buf = dz->sampbuf[5];
- double ip, op = 0.0, b1;
- for (i = chan ; i < dz->ssampsread; i+= STEREO) {
- ip = (double) buf[i];
- for (k = 0 ; k < dz->fltcnt; k++) {
- b1 = dz->fltmul * cn[k];
- op = (cn[k] * ip) + (den1[k] * s1[k]) + (den2[k] * s2[k]) + (b1 * e1[k]) + (cn[k] * e2[k]);
- s2[k] = s1[k];
- s1[k] = op;
- e2[k] = e1[k];
- e1[k] = ip;
- }
- if(op >= HUGE || op <= -HUGE) {
- sprintf(errstr,"Filter numeric overflow at %lf secs: try a different (higher) cutoff frequency.\n",
- (double)((dz->total_samps_written/dz->infile->channels) + (i/STEREO))/(double)dz->infile->srate);
- return GOAL_FAILED;
- }
- op *= dz->scalefact;
- if (fabs(op) > 1.0) {
- dz->scalefact *= .9999;
- if (op > 0.0)
- op = 1.0;
- else
- op = -1.0;
- }
- buf[i] = (float)op;
- }
- return FINISHED;
- }
- /********************************* SETUP_LPHP_FILTER *****************************/
- int setup_lphp_filter(dataptr dz)
- {
- int exit_status;
- int filter_order;
- double signd = 1.0, passfrq, stopfrq;
- dz->scalefact = 1.0; // Start with no prescaling: turn down if filter blows up
- passfrq = dz->param[FRAC_FFREQ];
- stopfrq = dz->param[FRAC_FFREQ] * 1.25;
- signd = -1.0;
- dz->fltmul = 2.0;
- filter_order = establish_order_of_filter(passfrq,stopfrq,dz);
- if((exit_status = allocate_internal_params_lphp(dz))<0)
- return(exit_status);
- calculate_filter_poles_lphp(signd,filter_order,passfrq,dz);
- initialise_filter_coeffs_lphp(dz);
- return(FINISHED);
- }
- /********************************* ESTABLISH_ORDER_OF_FILTER *****************************/
- int establish_order_of_filter(double passfrq,double stopfrq,dataptr dz)
- {
- int filter_order;
- double tc, tp, tt, pii, xx, yy, fltgain = FILTER_GAIN;
- double sr = (double)dz->infile->srate;
- pii = 4.0 * atan(1.0);
- passfrq = pii * passfrq/sr;
- tp = tan(passfrq);
- stopfrq = pii * stopfrq/sr;
- tc = tan(stopfrq);
- tt = tc / tp ;
- tt = (tt * tt);
- fltgain = fabs(fltgain);
- fltgain = fltgain * log(10.0)/10.0 ;
- fltgain = exp(fltgain) - 1.0 ;
- xx = log(fltgain)/log(tt) ;
- yy = floor(xx);
- if ((xx - yy) == 0.0 )
- yy = yy - 1.0 ;
- filter_order = ((int)yy) + 1;
- if (filter_order <= 1)
- filter_order = 2;
- dz->fltcnt = filter_order/2 ;
- filter_order = 2 * dz->fltcnt;
- dz->fltcnt = min(dz->fltcnt,200);
- filter_order = 2 * dz->fltcnt;
- return(filter_order);
- }
- /********************************* ALLOCATE_INTERNAL_PARAMS_LPHP *****************************/
- int allocate_internal_params_lphp(dataptr dz)
- {
- int fbase = dz->outlevs + 1;
- int i;
- if((dz->parray[fbase + FLT_DEN1] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_DEN2] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_CN] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_S1_BASE] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_E1_BASE] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_S2_BASE] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_E2_BASE] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
- return(MEMORY_ERROR);
- }
- for(i = 1; i < STEREO;i++) {
- int index = i*FLT_LPHP_ARRAYS_PER_FILTER;
- if((dz->parray[fbase + FLT_S1_BASE + index] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_E1_BASE + index] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_S2_BASE + index] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL
- || (dz->parray[fbase + FLT_E2_BASE + index] = (double *)calloc(dz->fltcnt * sizeof(double),sizeof(char)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for arrays of filter parameters.\n");
- return(MEMORY_ERROR);
- }
- }
- return(FINISHED);
- }
- /********************************* CALCULATE_FILTER_POLES_LPHP *****************************/
- void calculate_filter_poles_lphp(double signd,int filter_order,double passfrq,dataptr dz)
- {
- double ss, xx, aa, tppwr, x1, x2, cc;
- double pii = 4.0 * atan(1.0);
- double tp = tan(passfrq);
- int k;
- int fbase = dz->outlevs + 1;
- ss = pii / (double)(2 * filter_order);
- for (k = 0; k < dz->fltcnt; k++ ) {
- xx = (double) ((2.0 * (k+1)) - 1.0);
- aa = -sin(xx * ss);
- tppwr = pow(tp,2.0);
- cc = 1.0 - (2.0 * aa * tp) + tppwr;
- x1 = 2.0 * (tppwr - 1.0)/cc ;
- x2 = (1.0 + (2.0 * aa * tp) + tppwr)/cc ;
- dz->parray[fbase + FLT_DEN1][k] = signd * x1;
- dz->parray[fbase + FLT_DEN2][k] = -x2 ;
- dz->parray[fbase + FLT_CN][k] = pow(tp,2.0)/cc ;
- }
- }
- /********************************* INITIALISE_FILTER_COEFFS_LPHP *****************************/
- void initialise_filter_coeffs_lphp(dataptr dz)
- {
- int k;
- int i,index;
- int fbase = dz->outlevs + 1;
- for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
- dz->parray[fbase + FLT_S1_BASE][k] = 0.0;
- dz->parray[fbase + FLT_S2_BASE][k] = 0.0;
- dz->parray[fbase + FLT_E1_BASE][k] = 0.0;
- dz->parray[fbase + FLT_E2_BASE][k] = 0.0;
- }
- for(i=1;i < STEREO; i++){
- index = i * FLT_LPHP_ARRAYS_PER_FILTER;
- for (k = 0 ; k < dz->iparam[FLT_CNT]; k++) {
- dz->parray[fbase + FLT_S1_BASE + index][k] = 0.0;
- dz->parray[fbase + FLT_S2_BASE + index][k] = 0.0;
- dz->parray[fbase + FLT_E1_BASE + index][k] = 0.0;
- dz->parray[fbase + FLT_E2_BASE + index][k] = 0.0;
- }
- }
- }
- ////
- // HEREH When do we start the filtering ??
- // How do we use the finishing strategy for the filter tail ??
- // How do we test whether filter works (output filter !!!!)
- /**************************** ESTABLISH_ECHOS ***************************
- void establish_echos(int *maxdelay,dataptr dz)
- {
- int n;
- double *delay = dz->parray[dz->echobas]; // size 20
- double *gainl = dz->parray[dz->echobas + 1]; // size 20
- double *gainr = dz->parray[dz->echobas + 2]; // size 20
- double tdelay[] = {0.131832, 0.215038, 0.322274, 0.414122, 0.504488, 0.637713, 0.730468, 0.808751, 0.910460, 1.027041, 1.132028, 1.244272, 1.336923, 1.427700, 1.528503, 1.618661, 1.715413, 1.814730, 1.914843, 2.000258};
- double gain[] = {0.500000,0.354813,0.354813,0.251189,0.125893,0.125893,0.063096,0.063096,0.031623,0.031623,0.012589,0.012589,0.005012,0.005012,0.002512,0.002512,0.002512,0.002512,0.002512,0.002512};
- double pan[] = {.9,.5,-.5,0.1,.7,-.7,.3,-.3,.15,-.15,.85,-.85,.4,-.4,.6,-.6,.225,-.225,.775,-.775};
- for(n=0;n < dz->iparam[FRAC_ECHOCNT]; n++)
- delay[n] = (int)round(tdelay[n] * dz->infile->srate * dz->param[STAD_SIZE]) * STEREO;
- *maxdelay = delay[dz->iparam[FRAC_ECHOCNT - 1]];
- if(dz->param[FRAC_EROLL]<1.0) {
- for(n=0;n<dz->iparam[FRAC_ECHOCNT];n++)
- gain[n] = pow(gain[n],dz->param[FRAC_EROLL]);
- }
- for(n=0;n<dz->iparam[FRAC_ECHOCNT];n++) {
- if(pan[n] < 0.0) { // LEFTWARDS
- gainl[n] = gain[n] * dz->param[FRAC_EPREGN];
- gainr[n] = gain[n] * dz->param[FRAC_EPREGN] * (1.0+pan[n]);
- } else { // RIGHTWARDS
- gainl[n] = gain[n] * dz->param[FRAC_EPREGN] * (1.0-pan[n]);
- gainr[n] = gain[n] * dz->param[FRAC_EPREGN];
- }
- }
- }
- */
|