spin.c 130 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <structures.h>
  4. #include <tkglobals.h>
  5. #include <pnames.h>
  6. #include <filetype.h>
  7. #include <processno.h>
  8. #include <modeno.h>
  9. #include <logic.h>
  10. #include <globcon.h>
  11. #include <cdpmain.h>
  12. #include <math.h>
  13. #include <mixxcon.h>
  14. #include <osbind.h>
  15. #include <standalone.h>
  16. #include <science.h>
  17. #include <ctype.h>
  18. #include <sfsys.h>
  19. #include <string.h>
  20. #include <srates.h>
  21. #ifdef unix
  22. #define round(x) lround((x))
  23. #endif
  24. char errstr[2400];
  25. int anal_infiles = 1;
  26. int sloom = 0;
  27. int sloombatch = 0;
  28. #define ROOT2 (1.4142136)
  29. #define is_wide is_mapping
  30. #define is_bare_centre is_rectified
  31. #define pshift_factor is_sharp
  32. const char* cdp_version = "6.1.0";
  33. //CDP LIB REPLACEMENTS
  34. static int setup_spin_application(dataptr dz);
  35. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  36. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  37. static int setup_spin_param_ranges_and_defaults(dataptr dz);
  38. static int handle_the_extra_infile(char ***cmdline,int *cmdlinecnt,dataptr dz);
  39. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
  40. static int open_the_outfile(dataptr dz);
  41. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  42. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  43. static int establish_application(dataptr dz);
  44. static int initialise_vflags(dataptr dz);
  45. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  46. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  47. static int mark_parameter_types(dataptr dz,aplptr ap);
  48. static int assign_file_data_storage(int infilecnt,dataptr dz);
  49. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  50. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  51. static int get_the_mode_from_cmdline(char *str,dataptr dz);
  52. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  53. static int check_spin_param_validity_and_consistency(dataptr dz);
  54. static void pancalc(double position,double *leftgain,double *rightgain);
  55. static void time_display(int samps_sent,dataptr dz);
  56. static int create_spin_sndbufs(dataptr dz);
  57. static void calcgains(double *ch1pos,double *pos,double *lastspin,int *flipped,int *movingforward,double *leftgain,double *rightgain,double srate,dataptr dz);
  58. static void calcgains2(double *ch1pos,double *pos,double *lastspin,int *flipped,int *movingforward,double *leftgain,double *centregain,double *rightgain,double srate,dataptr dz);
  59. static void calcgains3(double *ch1pos,double *pos,double *lastspin,int *flipped,int *movingforward,double *leftgain,double *centregain,double *rightgain,
  60. double *ooleftgain, double *oileftgain, double *ocentregain, double *oirightgain, double *oorightgain, double srate,dataptr dz);
  61. static int spindopl(dataptr dz);
  62. static int spinwdopl(dataptr dz);
  63. static int spinwdopl2(dataptr dz);
  64. static int spinqdopl(dataptr dz);
  65. static int spinqdopl2(dataptr dz);
  66. /**************************************** MAIN *********************************************/
  67. int main(int argc,char *argv[])
  68. {
  69. int exit_status;
  70. dataptr dz = NULL;
  71. char **cmdline;
  72. int cmdlinecnt;
  73. int n;
  74. aplptr ap;
  75. int is_launched = FALSE;
  76. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  77. fprintf(stdout,"%s\n",cdp_version);
  78. fflush(stdout);
  79. return 0;
  80. }
  81. /* CHECK FOR SOUNDLOOM */
  82. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  83. sloom = 0;
  84. sloombatch = 1;
  85. }
  86. if(sflinit("cdp")){
  87. sfperror("cdp: initialisation\n");
  88. return(FAILED);
  89. }
  90. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  91. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  92. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  93. return(FAILED);
  94. }
  95. if(!sloom) {
  96. if(argc == 1) {
  97. usage1();
  98. return(FAILED);
  99. } else if(argc == 2) {
  100. usage2(argv[1]);
  101. return(FAILED);
  102. }
  103. }
  104. if(!sloom) {
  105. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  106. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  107. return(FAILED);
  108. }
  109. cmdline = argv;
  110. cmdlinecnt = argc;
  111. if((get_the_process_no(argv[0],dz))<0)
  112. return(FAILED);
  113. cmdline++;
  114. cmdlinecnt--;
  115. if(dz->process == SPIN)
  116. dz->maxmode = 3;
  117. else
  118. dz->maxmode = 2;
  119. if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
  120. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  121. return(exit_status);
  122. }
  123. cmdline++;
  124. cmdlinecnt--;
  125. dz->is_wide = 0;
  126. if(dz->process == SPINQ || dz->mode > 0)
  127. dz->is_wide = 1;
  128. dz->is_bare_centre = 0;
  129. if((dz->process == SPIN && dz->mode == 2) || (dz->process == SPINQ && dz->mode == 1))
  130. dz->is_bare_centre = 1;
  131. // setup_particular_application =
  132. if((exit_status = setup_spin_application(dz))<0) {
  133. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  134. return(FAILED);
  135. }
  136. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  137. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  138. return(FAILED);
  139. }
  140. } else {
  141. //parse_TK_data() =
  142. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  143. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  144. return(exit_status);
  145. }
  146. }
  147. ap = dz->application;
  148. // parse_infile_and_hone_type() =
  149. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  150. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  151. return(FAILED);
  152. }
  153. // setup_param_ranges_and_defaults() =
  154. if((exit_status = setup_spin_param_ranges_and_defaults(dz))<0) {
  155. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  156. return(FAILED);
  157. }
  158. // open_first_infile CDP LIB
  159. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  160. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  161. return(FAILED);
  162. }
  163. cmdlinecnt--;
  164. cmdline++;
  165. // handle_extra_infiles
  166. if(dz->process == SPINQ) {
  167. if((exit_status = handle_the_extra_infile(&cmdline,&cmdlinecnt,dz))<0) {
  168. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  169. return(FAILED);
  170. }
  171. }
  172. // handle_outfile() =
  173. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
  174. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  175. return(FAILED);
  176. }
  177. // handle_formants() redundant
  178. // handle_formant_quiksearch() redundant
  179. // handle_special_data() redundant
  180. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  181. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  182. return(FAILED);
  183. }
  184. // check_param_validity_and_consistency()
  185. if((exit_status = check_spin_param_validity_and_consistency(dz))<0) {
  186. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  187. return(FAILED);
  188. }
  189. if((exit_status = open_the_outfile(dz))<0) {
  190. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  191. return(FAILED);
  192. }
  193. is_launched = TRUE;
  194. if(dz->process == SPINQ)
  195. dz->bufcnt = 5;
  196. else
  197. dz->bufcnt = 3;
  198. if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
  199. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
  200. return(MEMORY_ERROR);
  201. }
  202. if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
  203. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
  204. return(MEMORY_ERROR);
  205. }
  206. for(n = 0;n <dz->bufcnt; n++)
  207. dz->sampbuf[n] = dz->sbufptr[n] = (float *)0;
  208. dz->sampbuf[n] = (float *)0;
  209. if((exit_status = create_spin_sndbufs(dz))<0) {
  210. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  211. return(FAILED);
  212. }
  213. //param_preprocess() redundant
  214. //spec_process_file =
  215. if(dz->process == SPIN) {
  216. switch(dz->mode) {
  217. case(0): exit_status = spindopl(dz); break;
  218. case(1): exit_status = spinwdopl(dz); break;
  219. case(2): exit_status = spinwdopl2(dz); break;
  220. }
  221. } else {
  222. switch(dz->mode) {
  223. case(0): exit_status = spinqdopl(dz); break;
  224. case(1): exit_status = spinqdopl2(dz); break;
  225. }
  226. }
  227. if(exit_status < 0) {
  228. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  229. return(FAILED);
  230. }
  231. if((exit_status = complete_output(dz))<0) { // CDP LIB
  232. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  233. return(FAILED);
  234. }
  235. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  236. free(dz);
  237. return(SUCCEEDED);
  238. }
  239. /**********************************************
  240. REPLACED CDP LIB FUNCTIONS
  241. **********************************************/
  242. /****************************** SET_PARAM_DATA *********************************/
  243. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  244. {
  245. ap->special_data = (char)special_data;
  246. ap->param_cnt = (char)paramcnt;
  247. ap->max_param_cnt = (char)maxparamcnt;
  248. if(ap->max_param_cnt>0) {
  249. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  250. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  251. return(MEMORY_ERROR);
  252. }
  253. strcpy(ap->param_list,paramlist);
  254. }
  255. return(FINISHED);
  256. }
  257. /****************************** SET_VFLGS *********************************/
  258. int set_vflgs
  259. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  260. {
  261. ap->option_cnt = (char) optcnt; /*RWD added cast */
  262. if(optcnt) {
  263. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  264. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  265. return(MEMORY_ERROR);
  266. }
  267. strcpy(ap->option_list,optlist);
  268. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  269. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  270. return(MEMORY_ERROR);
  271. }
  272. strcpy(ap->option_flags,optflags);
  273. }
  274. ap->vflag_cnt = (char) vflagcnt;
  275. ap->variant_param_cnt = (char) vparamcnt;
  276. if(vflagcnt) {
  277. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  278. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  279. return(MEMORY_ERROR);
  280. }
  281. strcpy(ap->variant_list,varlist);
  282. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  283. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  284. return(MEMORY_ERROR);
  285. }
  286. strcpy(ap->variant_flags,varflags);
  287. }
  288. return(FINISHED);
  289. }
  290. /***************************** APPLICATION_INIT **************************/
  291. int application_init(dataptr dz)
  292. {
  293. int exit_status;
  294. int storage_cnt;
  295. int tipc, brkcnt;
  296. aplptr ap = dz->application;
  297. if(ap->vflag_cnt>0)
  298. initialise_vflags(dz);
  299. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  300. ap->total_input_param_cnt = (char)tipc;
  301. if(tipc>0) {
  302. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  303. return(exit_status);
  304. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  305. return(exit_status);
  306. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  307. return(exit_status);
  308. }
  309. brkcnt = tipc;
  310. //THERE ARE NO INPUTFILE brktables USED IN THIS PROCESS
  311. if(brkcnt>0) {
  312. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  313. return(exit_status);
  314. }
  315. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  316. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  317. return(exit_status);
  318. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  319. return(exit_status);
  320. }
  321. if((exit_status = mark_parameter_types(dz,ap))<0)
  322. return(exit_status);
  323. // establish_infile_constants() replaced by
  324. dz->infilecnt = 1;
  325. //establish_bufptrs_and_extra_buffers():
  326. return(FINISHED);
  327. }
  328. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  329. /* RWD mallo changed to calloc; helps debug verison run as release! */
  330. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  331. {
  332. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  333. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  334. return(MEMORY_ERROR);
  335. }
  336. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  337. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  338. return(MEMORY_ERROR);
  339. }
  340. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  341. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  342. return(MEMORY_ERROR);
  343. }
  344. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  345. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  346. return(MEMORY_ERROR);
  347. }
  348. return(FINISHED);
  349. }
  350. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  351. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  352. {
  353. int n;
  354. for(n=0;n<storage_cnt;n++) {
  355. dz->is_int[n] = (char)0;
  356. dz->no_brk[n] = (char)0;
  357. }
  358. return(FINISHED);
  359. }
  360. /***************************** MARK_PARAMETER_TYPES **************************/
  361. int mark_parameter_types(dataptr dz,aplptr ap)
  362. {
  363. int n, m; /* PARAMS */
  364. for(n=0;n<ap->max_param_cnt;n++) {
  365. switch(ap->param_list[n]) {
  366. case('0'): break; /* dz->is_active[n] = 0 is default */
  367. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  368. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  369. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  370. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  371. default:
  372. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  373. return(PROGRAM_ERROR);
  374. }
  375. } /* OPTIONS */
  376. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  377. switch(ap->option_list[n]) {
  378. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  379. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  380. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  381. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  382. default:
  383. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  384. return(PROGRAM_ERROR);
  385. }
  386. } /* VARIANTS */
  387. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  388. switch(ap->variant_list[n]) {
  389. case('0'): break;
  390. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  391. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  392. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  393. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  394. default:
  395. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  396. return(PROGRAM_ERROR);
  397. }
  398. } /* INTERNAL */
  399. for(n=0,
  400. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  401. switch(ap->internal_param_list[n]) {
  402. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  403. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  404. case('d'): dz->no_brk[m] = (char)1; break;
  405. default:
  406. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  407. return(PROGRAM_ERROR);
  408. }
  409. }
  410. return(FINISHED);
  411. }
  412. /************************ HANDLE_THE_OUTFILE *********************/
  413. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
  414. {
  415. char *filename = (*cmdline)[0];
  416. if(filename[0]=='-' && filename[1]=='f') {
  417. dz->floatsam_output = 1;
  418. dz->true_outfile_stype = SAMP_FLOAT;
  419. filename+= 2;
  420. }
  421. if(!sloom) {
  422. if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
  423. sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
  424. return(DATA_ERROR);
  425. }
  426. }
  427. strcpy(dz->outfilename,filename);
  428. (*cmdline)++;
  429. (*cmdlinecnt)--;
  430. return(FINISHED);
  431. }
  432. /************************ OPEN_THE_OUTFILE *********************/
  433. int open_the_outfile(dataptr dz)
  434. {
  435. int exit_status, orig_chans = dz->infile->channels;
  436. if(dz->is_wide)
  437. dz->infile->channels = dz->iparam[SPNOCHNS];
  438. if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
  439. return(exit_status);
  440. dz->infile->channels = orig_chans;
  441. return(FINISHED);
  442. }
  443. /***************************** ESTABLISH_APPLICATION **************************/
  444. int establish_application(dataptr dz)
  445. {
  446. aplptr ap;
  447. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  448. sprintf(errstr,"establish_application()\n");
  449. return(MEMORY_ERROR);
  450. }
  451. ap = dz->application;
  452. memset((char *)ap,0,sizeof(struct applic));
  453. return(FINISHED);
  454. }
  455. /************************* INITIALISE_VFLAGS *************************/
  456. int initialise_vflags(dataptr dz)
  457. {
  458. int n;
  459. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  460. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  461. return(MEMORY_ERROR);
  462. }
  463. for(n=0;n<dz->application->vflag_cnt;n++)
  464. dz->vflag[n] = FALSE;
  465. return FINISHED;
  466. }
  467. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  468. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  469. {
  470. int n;
  471. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  472. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  473. return(MEMORY_ERROR);
  474. }
  475. for(n=0;n<tipc;n++)
  476. ap->default_val[n] = 0.0;
  477. return(FINISHED);
  478. }
  479. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  480. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  481. {
  482. int n;
  483. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  484. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  485. return(MEMORY_ERROR);
  486. }
  487. for(n=0;n<tipc;n++)
  488. dz->is_active[n] = (char)0;
  489. return(FINISHED);
  490. }
  491. /************************* SETUP_SPIN_APPLICATION *******************/
  492. int setup_spin_application(dataptr dz)
  493. {
  494. int exit_status;
  495. aplptr ap;
  496. if((exit_status = establish_application(dz))<0) // GLOBAL
  497. return(FAILED);
  498. ap = dz->application;
  499. // SEE parstruct FOR EXPLANATION of next 2 functions
  500. if(dz->is_wide)
  501. exit_status = set_param_data(ap,0 ,5,5,"Diidi");
  502. else
  503. exit_status = set_param_data(ap,0 ,5,2,"D00di");
  504. if(exit_status<0)
  505. return(FAILED);
  506. if(dz->is_wide) {
  507. if(dz->is_bare_centre)
  508. exit_status = set_vflgs(ap,"",0,"","bak",3,3,"ddd");
  509. else
  510. exit_status = set_vflgs(ap,"",0,"","bakc",4,4,"dddd");
  511. } else
  512. exit_status = set_vflgs(ap,"",0,"","ba",2,2,"dd");
  513. if(exit_status<0)
  514. return(FAILED);
  515. // set_legal_infile_structure -->
  516. dz->has_otherfile = FALSE;
  517. // assign_process_logic -->
  518. dz->input_data_type = SNDFILES_ONLY;
  519. dz->process_type = UNEQUAL_SNDFILE;
  520. dz->outfiletype = SNDFILE_OUT;
  521. return application_init(dz); //GLOBAL
  522. }
  523. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  524. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  525. {
  526. int exit_status;
  527. infileptr infile_info;
  528. if(!sloom) {
  529. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  530. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  531. return(MEMORY_ERROR);
  532. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  533. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  534. return(PROGRAM_ERROR);
  535. } else if(infile_info->filetype != SNDFILE) {
  536. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  537. return(DATA_ERROR);
  538. } else if(infile_info->channels != 2) {
  539. sprintf(errstr,"File %s is not of correct type (must be stereo)\n",cmdline[0]);
  540. return(DATA_ERROR);
  541. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  542. sprintf(errstr,"Failed to copy file parsing information\n");
  543. return(PROGRAM_ERROR);
  544. }
  545. free(infile_info);
  546. }
  547. return(FINISHED);
  548. }
  549. /************************ HANDLE_THE_EXTRA_INFILE *********************/
  550. int handle_the_extra_infile(char ***cmdline,int *cmdlinecnt,dataptr dz)
  551. {
  552. /* OPEN ONE EXTRA ANALFILE, CHECK COMPATIBILITY */
  553. int exit_status;
  554. char *filename;
  555. fileptr fp2;
  556. double maxamp, maxloc;
  557. int maxrep;
  558. int getmax = 0, getmaxinfo = 0;
  559. infileptr ifp;
  560. filename = (*cmdline)[0];
  561. if((dz->ifd[1] = sndopenEx(filename,0,CDP_OPEN_RDONLY)) < 0) {
  562. sprintf(errstr,"cannot open input file %s to read data.\n",filename);
  563. return(DATA_ERROR);
  564. }
  565. if((ifp = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  566. sprintf(errstr,"INSUFFICIENT MEMORY to store data on later infile. (1)\n");
  567. return(MEMORY_ERROR);
  568. }
  569. if((fp2 = (fileptr)malloc(sizeof(struct fileprops)))==NULL) {
  570. sprintf(errstr,"INSUFFICIENT MEMORY to store data on later infile. (2)\n");
  571. return(MEMORY_ERROR);
  572. }
  573. if((exit_status = readhead(ifp,dz->ifd[1],filename,&maxamp,&maxloc,&maxrep,getmax,getmaxinfo))<0)
  574. return(exit_status);
  575. copy_to_fileptr(ifp,fp2);
  576. if(fp2->filetype != SNDFILE) {
  577. sprintf(errstr,"%s is not a soundfile.\n",filename);
  578. return(DATA_ERROR);
  579. }
  580. if(fp2->channels != 2) {
  581. sprintf(errstr,"File %s is not of correct type (must be stereo)\n",filename);
  582. return(DATA_ERROR);
  583. }
  584. if((dz->insams[1] = sndsizeEx(dz->ifd[1]))<0) { /* FIND SIZE OF FILE */
  585. sprintf(errstr, "Can't read size of input file %s.\n", filename); //RWD added filename
  586. return(PROGRAM_ERROR);
  587. }
  588. if(dz->insams[1]==0) {
  589. sprintf(errstr, "File %s contains no data.\n",filename);
  590. return(DATA_ERROR);
  591. }
  592. (*cmdline)++;
  593. (*cmdlinecnt)--;
  594. return(FINISHED);
  595. }
  596. /************************* SETUP_SPIN_PARAM_RANGES_AND_DEFAULTS *******************/
  597. int setup_spin_param_ranges_and_defaults(dataptr dz)
  598. {
  599. int exit_status;
  600. aplptr ap = dz->application;
  601. // set_param_ranges()
  602. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  603. // NB total_input_param_cnt is > 0 !!!
  604. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  605. return(FAILED);
  606. // get_param_ranges()
  607. ap->lo[SPNRATE] = -100;
  608. ap->hi[SPNRATE] = 100.0;
  609. ap->default_val[SPNRATE] = 1;
  610. ap->lo[SPNBOOST] = 0;
  611. ap->hi[SPNBOOST] = 16;
  612. ap->default_val[SPNBOOST] = 2;
  613. ap->lo[SPNATTEN] = 0;
  614. ap->hi[SPNATTEN] = 1;
  615. ap->default_val[SPNATTEN] = 0;
  616. if(dz->is_wide) {
  617. if(dz->process == SPINQ)
  618. ap->lo[SPNOCHNS] = 5;
  619. else
  620. ap->lo[SPNOCHNS] = 4;
  621. ap->hi[SPNOCHNS] = 16;
  622. ap->default_val[SPNOCHNS] = 8;
  623. ap->lo[SPNOCNTR] = 1;
  624. ap->hi[SPNOCNTR] = 16;
  625. ap->default_val[SPNOCNTR] = 1;
  626. ap->lo[SPNCMIN] = 0;
  627. ap->hi[SPNCMIN] = 1;
  628. ap->default_val[SPNCMIN] = 0.0;
  629. if(!dz->is_bare_centre) {
  630. ap->lo[SPNCMAX] = 0;
  631. ap->hi[SPNCMAX] = 1;
  632. ap->default_val[SPNCMAX] = 0.5;
  633. }
  634. }
  635. ap->lo[SPNDOPL] = 0;
  636. ap->hi[SPNDOPL] = 12;
  637. ap->default_val[SPNDOPL] = 0.0;
  638. ap->lo[SPNXBUF] = 1;
  639. ap->hi[SPNXBUF] = 64;
  640. ap->default_val[SPNXBUF] = 1.0;
  641. if(dz->process == SPINQ)
  642. dz->maxmode = 2;
  643. else
  644. dz->maxmode = 3;
  645. if(!sloom)
  646. put_default_vals_in_all_params(dz);
  647. return(FINISHED);
  648. }
  649. /********************************* PARSE_SLOOM_DATA *********************************/
  650. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  651. {
  652. int exit_status;
  653. int cnt = 1, infilecnt;
  654. int filesize, insams, inbrksize;
  655. double dummy;
  656. int true_cnt = 0;
  657. aplptr ap;
  658. while(cnt<=PRE_CMDLINE_DATACNT) {
  659. if(cnt > argc) {
  660. sprintf(errstr,"Insufficient data sent from TK\n");
  661. return(DATA_ERROR);
  662. }
  663. switch(cnt) {
  664. case(1):
  665. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  666. sprintf(errstr,"Cannot read process no. sent from TK\n");
  667. return(DATA_ERROR);
  668. }
  669. break;
  670. case(2):
  671. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  672. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  673. return(DATA_ERROR);
  674. }
  675. if(dz->mode > 0)
  676. dz->mode--;
  677. //setup_particular_application() =
  678. dz->is_wide = 0;
  679. if(dz->process == SPINQ || dz->mode > 0)
  680. dz->is_wide = 1;
  681. dz->is_bare_centre = 0;
  682. if((dz->process == SPIN && dz->mode == 2) || (dz->process == SPINQ && dz->mode == 1))
  683. dz->is_bare_centre = 1;
  684. if((exit_status = setup_spin_application(dz))<0)
  685. return(exit_status);
  686. ap = dz->application;
  687. break;
  688. case(3):
  689. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  690. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  691. return(DATA_ERROR);
  692. }
  693. if(infilecnt < 1) {
  694. true_cnt = cnt + 1;
  695. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  696. }
  697. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  698. return(exit_status);
  699. break;
  700. case(INPUT_FILETYPE+4):
  701. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  702. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  703. return(DATA_ERROR);
  704. }
  705. break;
  706. case(INPUT_FILESIZE+4):
  707. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  708. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  709. return(DATA_ERROR);
  710. }
  711. dz->insams[0] = filesize;
  712. break;
  713. case(INPUT_INSAMS+4):
  714. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  715. sprintf(errstr,"Cannot read insams sent from TK\n");
  716. return(DATA_ERROR);
  717. }
  718. dz->insams[0] = insams;
  719. break;
  720. case(INPUT_SRATE+4):
  721. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  722. sprintf(errstr,"Cannot read srate sent from TK\n");
  723. return(DATA_ERROR);
  724. }
  725. break;
  726. case(INPUT_CHANNELS+4):
  727. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  728. sprintf(errstr,"Cannot read channels sent from TK\n");
  729. return(DATA_ERROR);
  730. }
  731. break;
  732. case(INPUT_STYPE+4):
  733. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  734. sprintf(errstr,"Cannot read stype sent from TK\n");
  735. return(DATA_ERROR);
  736. }
  737. break;
  738. case(INPUT_ORIGSTYPE+4):
  739. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  740. sprintf(errstr,"Cannot read origstype sent from TK\n");
  741. return(DATA_ERROR);
  742. }
  743. break;
  744. case(INPUT_ORIGRATE+4):
  745. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  746. sprintf(errstr,"Cannot read origrate sent from TK\n");
  747. return(DATA_ERROR);
  748. }
  749. break;
  750. case(INPUT_MLEN+4):
  751. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  752. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  753. return(DATA_ERROR);
  754. }
  755. break;
  756. case(INPUT_DFAC+4):
  757. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  758. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  759. return(DATA_ERROR);
  760. }
  761. break;
  762. case(INPUT_ORIGCHANS+4):
  763. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  764. sprintf(errstr,"Cannot read origchans sent from TK\n");
  765. return(DATA_ERROR);
  766. }
  767. break;
  768. case(INPUT_SPECENVCNT+4):
  769. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  770. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  771. return(DATA_ERROR);
  772. }
  773. dz->specenvcnt = dz->infile->specenvcnt;
  774. break;
  775. case(INPUT_WANTED+4):
  776. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  777. sprintf(errstr,"Cannot read wanted sent from TK\n");
  778. return(DATA_ERROR);
  779. }
  780. break;
  781. case(INPUT_WLENGTH+4):
  782. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  783. sprintf(errstr,"Cannot read wlength sent from TK\n");
  784. return(DATA_ERROR);
  785. }
  786. break;
  787. case(INPUT_OUT_CHANS+4):
  788. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  789. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  790. return(DATA_ERROR);
  791. }
  792. break;
  793. /* RWD these chanegs to samps - tk will have to deal with that! */
  794. case(INPUT_DESCRIPTOR_BYTES+4):
  795. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  796. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  797. return(DATA_ERROR);
  798. }
  799. break;
  800. case(INPUT_IS_TRANSPOS+4):
  801. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  802. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  803. return(DATA_ERROR);
  804. }
  805. break;
  806. case(INPUT_COULD_BE_TRANSPOS+4):
  807. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  808. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  809. return(DATA_ERROR);
  810. }
  811. break;
  812. case(INPUT_COULD_BE_PITCH+4):
  813. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  814. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  815. return(DATA_ERROR);
  816. }
  817. break;
  818. case(INPUT_DIFFERENT_SRATES+4):
  819. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  820. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  821. return(DATA_ERROR);
  822. }
  823. break;
  824. case(INPUT_DUPLICATE_SNDS+4):
  825. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  826. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  827. return(DATA_ERROR);
  828. }
  829. break;
  830. case(INPUT_BRKSIZE+4):
  831. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  832. sprintf(errstr,"Cannot read brksize sent from TK\n");
  833. return(DATA_ERROR);
  834. }
  835. if(inbrksize > 0) {
  836. switch(dz->input_data_type) {
  837. case(WORDLIST_ONLY):
  838. break;
  839. case(PITCH_AND_PITCH):
  840. case(PITCH_AND_TRANSPOS):
  841. case(TRANSPOS_AND_TRANSPOS):
  842. dz->tempsize = inbrksize;
  843. break;
  844. case(BRKFILES_ONLY):
  845. case(UNRANGED_BRKFILE_ONLY):
  846. case(DB_BRKFILES_ONLY):
  847. case(ALL_FILES):
  848. case(ANY_NUMBER_OF_ANY_FILES):
  849. if(dz->extrabrkno < 0) {
  850. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  851. return(DATA_ERROR);
  852. }
  853. if(dz->brksize == NULL) {
  854. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  855. return(PROGRAM_ERROR);
  856. }
  857. dz->brksize[dz->extrabrkno] = inbrksize;
  858. break;
  859. default:
  860. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  861. dz->input_data_type);
  862. return(PROGRAM_ERROR);
  863. }
  864. break;
  865. }
  866. break;
  867. case(INPUT_NUMSIZE+4):
  868. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  869. sprintf(errstr,"Cannot read numsize sent from TK\n");
  870. return(DATA_ERROR);
  871. }
  872. break;
  873. case(INPUT_LINECNT+4):
  874. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  875. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  876. return(DATA_ERROR);
  877. }
  878. break;
  879. case(INPUT_ALL_WORDS+4):
  880. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  881. sprintf(errstr,"Cannot read all_words sent from TK\n");
  882. return(DATA_ERROR);
  883. }
  884. break;
  885. case(INPUT_ARATE+4):
  886. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  887. sprintf(errstr,"Cannot read arate sent from TK\n");
  888. return(DATA_ERROR);
  889. }
  890. break;
  891. case(INPUT_FRAMETIME+4):
  892. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  893. sprintf(errstr,"Cannot read frametime sent from TK\n");
  894. return(DATA_ERROR);
  895. }
  896. dz->frametime = (float)dummy;
  897. break;
  898. case(INPUT_WINDOW_SIZE+4):
  899. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  900. sprintf(errstr,"Cannot read window_size sent from TK\n");
  901. return(DATA_ERROR);
  902. }
  903. break;
  904. case(INPUT_NYQUIST+4):
  905. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  906. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  907. return(DATA_ERROR);
  908. }
  909. break;
  910. case(INPUT_DURATION+4):
  911. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  912. sprintf(errstr,"Cannot read duration sent from TK\n");
  913. return(DATA_ERROR);
  914. }
  915. break;
  916. case(INPUT_MINBRK+4):
  917. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  918. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  919. return(DATA_ERROR);
  920. }
  921. break;
  922. case(INPUT_MAXBRK+4):
  923. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  924. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  925. return(DATA_ERROR);
  926. }
  927. break;
  928. case(INPUT_MINNUM+4):
  929. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  930. sprintf(errstr,"Cannot read minnum sent from TK\n");
  931. return(DATA_ERROR);
  932. }
  933. break;
  934. case(INPUT_MAXNUM+4):
  935. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  936. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  937. return(DATA_ERROR);
  938. }
  939. break;
  940. default:
  941. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  942. return(PROGRAM_ERROR);
  943. }
  944. cnt++;
  945. }
  946. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  947. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  948. return(DATA_ERROR);
  949. }
  950. if(true_cnt)
  951. cnt = true_cnt;
  952. *cmdlinecnt = 0;
  953. while(cnt < argc) {
  954. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  955. return(exit_status);
  956. cnt++;
  957. }
  958. return(FINISHED);
  959. }
  960. /********************************* GET_TK_CMDLINE_WORD *********************************/
  961. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  962. {
  963. if(*cmdlinecnt==0) {
  964. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  965. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  966. return(MEMORY_ERROR);
  967. }
  968. } else {
  969. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  970. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  971. return(MEMORY_ERROR);
  972. }
  973. }
  974. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  975. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  976. return(MEMORY_ERROR);
  977. }
  978. strcpy((*cmdline)[*cmdlinecnt],q);
  979. (*cmdlinecnt)++;
  980. return(FINISHED);
  981. }
  982. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  983. int assign_file_data_storage(int infilecnt,dataptr dz)
  984. {
  985. int exit_status;
  986. int no_sndfile_system_files = FALSE;
  987. dz->infilecnt = infilecnt;
  988. if((exit_status = allocate_filespace(dz))<0)
  989. return(exit_status);
  990. if(no_sndfile_system_files)
  991. dz->infilecnt = 0;
  992. return(FINISHED);
  993. }
  994. /************************* redundant functions: to ensure libs compile OK *******************/
  995. int assign_process_logic(dataptr dz)
  996. {
  997. return(FINISHED);
  998. }
  999. void set_legal_infile_structure(dataptr dz)
  1000. {}
  1001. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  1002. {
  1003. return(FINISHED);
  1004. }
  1005. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1006. {
  1007. return(FINISHED);
  1008. }
  1009. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1010. {
  1011. return(FINISHED);
  1012. }
  1013. int read_special_data(char *str,dataptr dz)
  1014. {
  1015. return(FINISHED);
  1016. }
  1017. int inner_loop
  1018. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1019. {
  1020. return(FINISHED);
  1021. }
  1022. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1023. {
  1024. return(FINISHED);
  1025. }
  1026. /******************************** USAGE1 ********************************/
  1027. int usage1(void)
  1028. {
  1029. fprintf(stderr,
  1030. "USAGE: spin NAME mode infile outfile (parameters)\n"
  1031. "\n"
  1032. "where NAME can be any one of\n"
  1033. "\n"
  1034. "stereo quad\n"
  1035. "\n"
  1036. "Type 'spin stereo' for more info on spin stereo option... ETC.\n");
  1037. return(USAGE_ONLY);
  1038. }
  1039. /******************************** DBTOLEVEL ***********************/
  1040. double dbtolevel(double val)
  1041. {
  1042. int isneg = 0;
  1043. if(flteq(val,0.0))
  1044. return(1.0);
  1045. if(val < 0.0) {
  1046. val = -val;
  1047. isneg = 1;
  1048. }
  1049. val /= 20.0;
  1050. val = pow(10.0,val);
  1051. if(isneg)
  1052. val = 1.0/val;
  1053. return(val);
  1054. }
  1055. /********************************************************************************************/
  1056. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1057. {
  1058. if(!strcmp(prog_identifier_from_cmdline,"stereo")) dz->process = SPIN;
  1059. else if(!strcmp(prog_identifier_from_cmdline,"quad")) dz->process = SPINQ;
  1060. else {
  1061. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  1062. return(USAGE_ONLY);
  1063. }
  1064. return(FINISHED);
  1065. }
  1066. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  1067. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  1068. {
  1069. int n;
  1070. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  1071. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  1072. return(MEMORY_ERROR);
  1073. }
  1074. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  1075. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  1076. return(MEMORY_ERROR);
  1077. }
  1078. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1079. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  1080. return(MEMORY_ERROR);
  1081. }
  1082. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1083. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  1084. return(MEMORY_ERROR);
  1085. }
  1086. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1087. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  1088. return(MEMORY_ERROR);
  1089. }
  1090. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1091. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  1092. return(MEMORY_ERROR);
  1093. }
  1094. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1095. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  1096. return(MEMORY_ERROR);
  1097. }
  1098. for(n=0;n<brkcnt;n++) {
  1099. dz->brk[n] = NULL;
  1100. dz->brkptr[n] = NULL;
  1101. dz->brkinit[n] = 0;
  1102. dz->brksize[n] = 0;
  1103. }
  1104. return(FINISHED);
  1105. }
  1106. /******************************** USAGE2 ********************************/
  1107. int usage2(char *str)
  1108. {
  1109. if(!strcmp(str,"stereo")) {
  1110. fprintf(stderr,
  1111. "USAGE: spin stereo\n"
  1112. "1 inf outf rate dopl xbuf [-bboost] [-aatten] [-eexpbuf]\n"
  1113. "2 inf outf rate chns cntr dopl xbuf [-bboost] [-aatt] [-kcmn] [-ccmx]\n"
  1114. "3 inf outf rate chns cntr dopl xbuf [-bboost] [-aatt] [-kcmn]\n"
  1115. "\n"
  1116. "Spin a wide stereo-image across the stereo space.\n"
  1117. "(with possible doppler-shift on the moving edges).\n"
  1118. "\n"
  1119. "MODES 2 & 3 create 3-chan-wide output, centred on channel \"centre\",\n"
  1120. " in an \"ochans\"-channel outfile.\n"
  1121. "\n"
  1122. "When the spinning image crosses the centre ....\n"
  1123. "MODE 2 uses outer channels to project stereo-at-centre image.\n"
  1124. "MODE 3 uses ONLY central channel to project stereo-at-centre image.\n"
  1125. "\n"
  1126. "RATE spin speed in cycles per second (can vary over time).\n"
  1127. " Positive values spin clockwise (as viewed from above).\n"
  1128. " Negative values spin anticlockwise (as viewed from above).\n"
  1129. "BOOST Multiplicative level changes, as edges pass through centre.\n"
  1130. " gradually increase (*boost) as edge passes \"FRONT\" centre\n"
  1131. " and decreases (*1/boost) as edge passes \"REAR\" centre.\n"
  1132. " The two edges pass through centre simultaneously\n"
  1133. " so one edge gets louder and the other quieter.\n"
  1134. "ATT overall level attenuation (*att) as BOTH edges pass thro centre.\n"
  1135. "DOPL Max doppler pitchshift, in semitones (Range 0-12).\n"
  1136. "XBUF Expand buffers by this factor (may be ness for large doppler shift)\n"
  1137. "\n"
  1138. "Mode 2 & 3 only...\n"
  1139. "CHNS Number of channels in output file.\n"
  1140. "CNTR Output channel which carries the central channel of the output.\n"
  1141. "CMN Min level on centre lspkr (0-1).\n"
  1142. "Mode 2 only...\n"
  1143. "CMX Max level on centre lspkr (0-1).\n"
  1144. "\n"
  1145. "\n");
  1146. } else if(!strcmp(str,"quad")) {
  1147. fprintf(stderr,
  1148. "USAGE: spin quad 1 inf1 inf2 outf\n"
  1149. "rate ochns cntr dopl xbuf [-bboost] [-aatt] [-kcmn] [-ccmx]\n"
  1150. "OR: spin quad 2 inf1 inf2 outf\n"
  1151. "rate ochns cntr dopl xbuf [-bboost] [-aatt] [-kcmn]\n"
  1152. "\n"
  1153. "Spin two wide stereo-image across a 5-channel-wide sound image\n"
  1154. "(with possible doppler pitch-shift of the moving edges).\n"
  1155. "\n"
  1156. "When the spinning image crosses the centre ....\n"
  1157. "MODE 1 uses outer channels to project stereo-at-centre image.\n"
  1158. "MODE 2 uses ONLY central channel to project stereo-at-centre image.\n"
  1159. "\n"
  1160. "RATE spin speed in cycles per second (can vary over time).\n"
  1161. " Positive values spin clockwise (as viewed from above).\n"
  1162. " Negative values spin anticlockwise (as viewed from above).\n"
  1163. "OCHNS Number of channels in output file.\n"
  1164. "CNTR Output channel which carries the central channel of the 5 outputs.\n"
  1165. "DOPL Max doppler pitchshift, in semitones (Range 0-12).\n"
  1166. "XBUF Expand buffers used by process (may be nesss for large doppler shift)\n"
  1167. "BOOST Multiplicative level changes, as edges pass through centre.\n"
  1168. " gradually increase (*boost) as edge passes \"FRONT\" centre\n"
  1169. " and decreases (*1/boost) as edge passes \"REAR\" centre.\n"
  1170. " The two edges pass through centre simultaneously\n"
  1171. " so one edge gets louder and the other quieter.\n"
  1172. "ATT overall level decrease (*atten) as BOTH edges pass thro centre.\n"
  1173. "CMN Min level on centre lspkr (0-1).\n"
  1174. "Mode 2 only...\n"
  1175. "CMX Max level on centre lspkr (0-1).\n"
  1176. "\n");
  1177. } else
  1178. fprintf(stdout,"Unknown option '%s'\n",str);
  1179. return(USAGE_ONLY);
  1180. }
  1181. int usage3(char *str1,char *str2)
  1182. {
  1183. fprintf(stderr,"Insufficient parameters on command line.\n");
  1184. return(USAGE_ONLY);
  1185. }
  1186. /************************************ PANCALC *******************************/
  1187. #define SIGNAL_TO_LEFT (0)
  1188. #define SIGNAL_TO_RIGHT (1)
  1189. void pancalc(double position,double *leftgain,double *rightgain)
  1190. {
  1191. int dirflag;
  1192. double temp;
  1193. double relpos;
  1194. double reldist, invsquare;
  1195. if(position < 0.0)
  1196. dirflag = SIGNAL_TO_LEFT; /* signal on left */
  1197. else
  1198. dirflag = SIGNAL_TO_RIGHT;
  1199. if(position < 0)
  1200. relpos = -position;
  1201. else
  1202. relpos = position;
  1203. if(relpos <= 1.0){ /* between the speakers */
  1204. temp = 1.0 + (relpos * relpos);
  1205. reldist = ROOT2 / sqrt(temp);
  1206. temp = (position + 1.0) / 2.0;
  1207. *rightgain = temp * reldist;
  1208. *leftgain = (1.0 - temp ) * reldist;
  1209. } else { /* outside the speakers */
  1210. temp = (relpos * relpos) + 1.0;
  1211. reldist = sqrt(temp) / ROOT2; /* relative distance to source */
  1212. invsquare = 1.0 / (reldist * reldist);
  1213. if(dirflag == SIGNAL_TO_LEFT) {
  1214. *leftgain = invsquare;
  1215. *rightgain = 0.0;
  1216. } else { /* SIGNAL_TO_RIGHT */
  1217. *rightgain = invsquare;
  1218. *leftgain = 0;
  1219. }
  1220. }
  1221. }
  1222. /******************************* TIME_DISPLAY **************************/
  1223. void time_display(int samps_sent,dataptr dz)
  1224. {
  1225. if(sloom)
  1226. dz->process = MTOS;
  1227. display_virtual_time(samps_sent,dz);
  1228. if(sloom)
  1229. dz->process = BROWNIAN;
  1230. }
  1231. /****************************** GET_MODE *********************************/
  1232. int get_the_mode_from_cmdline(char *str,dataptr dz)
  1233. {
  1234. char temp[200], *p;
  1235. if(sscanf(str,"%s",temp)!=1) {
  1236. sprintf(errstr,"Cannot read mode of program.\n");
  1237. return(USAGE_ONLY);
  1238. }
  1239. p = temp + strlen(temp) - 1;
  1240. while(p >= temp) {
  1241. if(!isdigit(*p)) {
  1242. fprintf(stderr,"Invalid mode of program entered.\n");
  1243. return(USAGE_ONLY);
  1244. }
  1245. p--;
  1246. }
  1247. if(sscanf(str,"%d",&dz->mode)!=1) {
  1248. fprintf(stderr,"Cannot read mode of program.\n");
  1249. return(USAGE_ONLY);
  1250. }
  1251. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  1252. fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  1253. return(USAGE_ONLY);
  1254. }
  1255. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  1256. return(FINISHED);
  1257. }
  1258. /******************************** CHECK_SPIN_PARAM_VALIDITY_AND_CONSISTENCY *****************/
  1259. int check_spin_param_validity_and_consistency(dataptr dz)
  1260. {
  1261. int exit_status;
  1262. if(dz->is_wide) {
  1263. if(dz->iparam[SPNOCNTR] > dz->iparam[SPNOCHNS]) {
  1264. sprintf(errstr,"Centre channel (%d) is not within the range of output channels available (%d).\n",dz->iparam[SPNOCNTR],dz->iparam[SPNOCHNS]);
  1265. return DATA_ERROR;
  1266. }
  1267. if(!dz->is_bare_centre) {
  1268. if(dz->param[SPNCMIN] > dz->param[SPNCMAX]) {
  1269. sprintf(errstr,"Minimum level at centre (%lf) cannot be greater than maximum (%lf).\n",dz->param[SPNCMIN],dz->param[SPNCMAX]);
  1270. return DATA_ERROR;
  1271. }
  1272. }
  1273. }
  1274. if(dz->brksize[SPNRATE]) {
  1275. if((exit_status = get_maxvalue_in_brktable(&(dz->param[SPNRATE]),SPNRATE,dz))<0)
  1276. return exit_status;
  1277. } // Convert semitones to octaves
  1278. dz->param[SPNDOPL] /= SEMITONES_PER_OCTAVE; // NB at max speed, doplshift = speed*pshift_factor = dopl * maxspeed/maxspeed
  1279. dz->pshift_factor = dz->param[SPNDOPL]/dz->param[SPNRATE]; // at halfspeed, doplshift = halfspeed*pshift_factor = dopl * halfspeed/maxspeed = halfshift
  1280. return FINISHED; // at zerospeed, doplshift = 0*pshift_factor = 0
  1281. }
  1282. /******************************** CREATE_SPIN_SNDBUFS *****************/
  1283. int create_spin_sndbufs(dataptr dz)
  1284. {
  1285. int bigbufsize;
  1286. int frameunit, framesize, outbufsize;
  1287. int outchans;
  1288. if(dz->is_wide)
  1289. outchans = dz->iparam[SPNOCHNS];
  1290. else
  1291. outchans = STEREO;
  1292. frameunit = outchans + STEREO + STEREO; // frame must be a multiple of (changroupsize of input*2 (2 input bufs) + changroupsize of output)
  1293. if(dz->process == SPINQ)
  1294. frameunit += STEREO + STEREO; // Two extra stereo inputs
  1295. framesize = F_SECSIZE * frameunit; // frame must also be a multiple of sectorsize
  1296. if(dz->sbufptr == 0 || dz->sampbuf==0) {
  1297. sprintf(errstr,"buffer pointers not allocated: create_sndbufs()\n");
  1298. return(PROGRAM_ERROR);
  1299. }
  1300. bigbufsize = (int)Malloc(-1);
  1301. dz->buflen = bigbufsize / sizeof(float); // Ensure buffer contains an integer number of frames
  1302. dz->buflen = (dz->buflen / framesize) * framesize;
  1303. bigbufsize = dz->buflen * sizeof(float);
  1304. if(dz->iparam[SPNXBUF] > 1) {
  1305. bigbufsize *= dz->iparam[SPNXBUF];
  1306. dz->buflen *= dz->iparam[SPNXBUF];
  1307. }
  1308. if(bigbufsize <= 0) {
  1309. sprintf(errstr,"Not enough memory available for expanded buffers\n");
  1310. return MEMORY_ERROR;
  1311. }
  1312. outbufsize = (dz->buflen/frameunit) * outchans; // Get output buffer size
  1313. dz->buflen = (dz->buflen/frameunit) * STEREO; // Get TRUE (input) buffer size
  1314. bigbufsize += STEREO * 2 * sizeof(float); // create extra space for wraparound points of 2-input-bufs for interp of vals at buffer end
  1315. if(dz->process == SPINQ) // ..and in this case, also accomodate wraparound points of 2-bufs of 2nd-infile.
  1316. bigbufsize += STEREO * 2 * sizeof(float);
  1317. if((dz->bigbuf = (float *)malloc(bigbufsize)) == NULL) {
  1318. sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
  1319. return(PROGRAM_ERROR);
  1320. }
  1321. dz->buflen += STEREO; // accomodate wraparound points in calculating buffer boundaries
  1322. if(dz->process == SPINQ) {
  1323. dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf;
  1324. dz->sbufptr[1] = dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
  1325. dz->sbufptr[2] = dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen;
  1326. dz->sbufptr[3] = dz->sampbuf[3] = dz->sampbuf[2] + dz->buflen; // Each input file has 2 buffers, 1 to read left chan, other to read right
  1327. dz->sbufptr[4] = dz->sampbuf[4] = dz->sampbuf[3] + dz->buflen; // Reads may be out of sync,
  1328. dz->sampbuf[5] = dz->sampbuf[4] + outbufsize; // and left-read may exhaust buffer before right-read (or v.v.)
  1329. } else {
  1330. dz->sbufptr[0] = dz->sampbuf[0] = dz->bigbuf;
  1331. dz->sbufptr[1] = dz->sampbuf[1] = dz->sampbuf[0] + dz->buflen;
  1332. dz->sbufptr[2] = dz->sampbuf[2] = dz->sampbuf[1] + dz->buflen;
  1333. dz->sampbuf[3] = dz->sampbuf[2] + outbufsize;
  1334. }
  1335. dz->buflen -= STEREO;
  1336. return(FINISHED);
  1337. }
  1338. /******************************** CALCGAINS *****************/
  1339. void calcgains(double *ch1pos,double *pos,double *lastspin,int *flipped,int *movingforward,double *leftgain,double *rightgain,double srate,dataptr dz)
  1340. {
  1341. double cycleincr, lgain, rgain;
  1342. cycleincr = dz->param[SPNRATE]/srate; // How far into the rotation cycle, per sample-group
  1343. *ch1pos += cycleincr;
  1344. // Moving up, from 0 towards 1
  1345. if(cycleincr > 0.0) {
  1346. // If rotate changes direction,
  1347. if(*lastspin < 0.0) // if leaving centre after passing it (flipped), we're now approaching it (!flipped)
  1348. *flipped = !(*flipped); // whereas if approaching centre before passing it (!flipped), we're now leaving it (flipped)
  1349. if(!(*flipped)) { // If we've not previously reached 1/2 way through cycle (travelling up cycle)
  1350. if(*ch1pos > 0.5) { // If we've now reached 1/2 cycle end (Left-channel moved fully from L(-1) to R(1), 1/2 way up (-cos)-table)
  1351. *movingforward = -(*movingforward);// This edge starts to move backwards(if previously moving forwards) (or vice versa),
  1352. *flipped = 1; // and FLAG the fact we've passed the flip-point
  1353. }
  1354. }
  1355. if(*ch1pos > 1.0) { // If we've now reached full cycle end (the end of the (-cos) table, so we're back to start from -1 0 1 0 to -1)
  1356. *flipped = 0; // reset the flip-flag
  1357. *movingforward = -(*movingforward); // This edge starts to move forwards again (if previously backwards) (or vice versa)
  1358. *ch1pos -= 1.0; // reset ch1pos within 0-1 range (0-2PI range of (-cos) table)
  1359. }
  1360. *lastspin = dz->param[SPNRATE]; // Only set "lastspin" when spin is NON-zero, so system remembers last (non-zero) motion direction
  1361. } else if(cycleincr < 0.0) { // Opposite logic, moving down from 1 to 0
  1362. if(*lastspin > 0.0)
  1363. *flipped = !(*flipped);
  1364. if(!(*flipped)) { // If we've not previously reached 1/2 way through cycle (travelling down cycle)
  1365. if(*ch1pos < 0.5) { // If we've now reached 1/2 cycle end (Left-channel moved fully from L(-1) to R(1), 1/2 way down (-cos)-table)
  1366. *movingforward = -(*movingforward); // This edge starts to move backwards(if previously moving forwards) (or vice versa),
  1367. *flipped = 1; // and FLAG the fact we've passed the flip-point
  1368. }
  1369. }
  1370. if(*ch1pos < 0.0) { // If we've now reached full cycle end (the start of the (-cos) table, so we're back to start from -1 0 1 0 to -1)
  1371. *flipped = 0; // reset the flip-flag
  1372. *movingforward = -(*movingforward); // This edge starts to move forwards again (if previously backwards) (or vice versa)
  1373. *ch1pos += 1.0; // reset ch1pos within 0-1 range (0-2PI range of (-cos) table)
  1374. }
  1375. *lastspin = dz->param[SPNRATE];
  1376. }
  1377. *pos = -cos(*ch1pos * TWOPI); // ch1pos ranges from 0 to 1 and recycles, change range to 0 to 2PI
  1378. // -cos goes then ranges (-1 0 1 0 -1 = Left Right Left)
  1379. pancalc(*pos,&lgain,&rgain);
  1380. *leftgain = lgain;
  1381. *rightgain = rgain;
  1382. }
  1383. /******************************** SPINDOPL ********************************
  1384. *
  1385. * Everything is controlled by the parameter ch1pos.
  1386. * which cycles 0 -> 1, then flips back to 0, at a speed controlled by ROTATION RATE.
  1387. *
  1388. * Using this cycling function, "calcgains" calculates
  1389. *
  1390. * (1) "pos" ... the current position of the (original) left edge of the image, in the stereo-rotation space.
  1391. * (2) "leftgain" and "rightgain", the required weightings on left and right channel of output to place this at position "pos" in output.
  1392. * (3) "rleftgain" and "rrightgain", the weightings of the (orig) right channel-src (BY ANTI-SYMMETRY) in output image.
  1393. *
  1394. * The doppler logic is as follows
  1395. *
  1396. * If the rotation is +ve, if pos (spatial position) -ve (to left) , motion is away from listener, pitch falls, sampleread-incr +ve
  1397. * if pos +ve (to right), motion is towards listener, pitch rises, sampleread-incr -ve
  1398. *
  1399. * Speed varies sinusoidally from max at position -1(left) and +1(right) to min at 0(centre)
  1400. * so pitch-incr depends on position (which is varying sinusoidally) but inversely (pos to left (-ve) gives +ve sampread-incr).
  1401. * the step thro the pitch-table for +ve rotation is thus multipled by a factor X*(-pos)
  1402. *
  1403. * If the rotation is -ve, if pos -ve (to left) , motion is towards listener, pitch rises, sampread-incr -ve
  1404. * if pos +ve (to right), motion is away from listener, pitch falls, sampread-incr +ve
  1405. * the step thro the pitch-table for -ve rotation is thus multipled by a factor X*(pos)
  1406. *
  1407. * in general pitch-incr = (X*-rotsign*pos) ... pos varying between -1 and + 1
  1408. *
  1409. * We want pitch-incr to increase, as rotation-speed increases
  1410. *
  1411. * so pitch-incr = (Y*-rotrate*pos)
  1412. *
  1413. * User enters the MAXIMUM pitchshift required ... using the maximum rotation-rate, we calculate the "pshift_factor"
  1414. * The "pshift_factor" is the pshift per cycles-per-sec
  1415. *
  1416. * so pitch-incr = (pshift_factor*-rotrate*pos)
  1417. *
  1418. * !!!!!!!!!!!!!
  1419. *
  1420. * pos = spatial position of(originally) left channel of rotating source
  1421. *
  1422. * Data is read from two parallel buffers, which are topped up once either pointer reaches its buffer end
  1423. * either by a file-read, or by copying from the other (already read-into) buffer.
  1424. * Only when both read-processes reach their data-ends does process terminate.
  1425. *
  1426. * iposl = pointer to possibly-fractional read-position in input-buffer for read of (orig) left chan, counted in stereo-samples
  1427. * iposr = simil for (orig) right channel: Due to inverse doppler shifting, these read points are generally out of step, hence the 2 read buffers.
  1428. */
  1429. int spindopl(dataptr dz)
  1430. {
  1431. int exit_status, passno = 0, flipped = 0, movingforward, buf_advanced_l, buf_advanced_r;
  1432. float *ibufl = dz->sampbuf[0], *ibufr = dz->sampbuf[1], *obuf = dz->sampbuf[2];
  1433. double srate = (double)dz->infile->srate, iposl, iposr;
  1434. double ch1pos, normaliser = 1.0, maxsamp = 0.0, time = 0.0, firstspin, lastspin;
  1435. double pos, leftgain, lleftgain, rleftgain, rightgain, lrightgain, rrightgain, boost, atten, frac, diff, lval, rval, incrl, incrr;
  1436. int c1, c2, n, stereo_pairs_read, stereo_pairs_read_l, stereo_pairs_read_r, lo, hi;
  1437. int sampsread_l, sampsread_r, stereo_pairs_buflen = dz->buflen/STEREO;
  1438. if(dz->brksize[SPNRATE]) {
  1439. if((exit_status= read_value_from_brktable(time,SPNRATE,dz))< 0)
  1440. return exit_status;
  1441. }
  1442. firstspin = dz->param[SPNRATE];
  1443. for(passno = 0;passno < 2; passno++) {
  1444. dz->total_samps_written = 0;
  1445. iposl = 0;
  1446. iposr = 0;
  1447. display_virtual_time(dz->total_samps_written,dz);
  1448. ch1pos = 0; // ch1pos starts at beginning of motion-cycle range (0 of 0to1)
  1449. if(firstspin >= 0.0)
  1450. movingforward = 1; // Left image moves backwards (right image moves forwards) - clockwise, viewed from above
  1451. else
  1452. movingforward = -1; // Left image moves forward (right image moves backwards) - anticlockwise, viewed from above
  1453. lastspin = firstspin;
  1454. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1455. dz->total_samps_read = 0;
  1456. dz->samps_left = dz->insams[0];
  1457. if((sndseekEx(dz->ifd[0],0,0) < 0)){
  1458. sprintf(errstr,"sndseek failed\n");
  1459. return SYSTEM_ERROR;
  1460. }
  1461. c1 = 0; // current left sample of output buffer
  1462. c2 = 1; // current right sample of output buffer
  1463. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1464. memset((char *)ibufl,0,(dz->buflen + STEREO) * sizeof(float));
  1465. memset((char *)ibufr,0,(dz->buflen + STEREO) * sizeof(float));
  1466. dz->buflen += STEREO; // accomodate wrap-around points
  1467. if((exit_status = read_samps(ibufl,dz))<0)
  1468. return(exit_status);
  1469. memcpy((char *)ibufr,(char *)ibufl,dz->ssampsread * sizeof(float));
  1470. dz->buflen -= STEREO;
  1471. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  1472. dz->ssampsread -= STEREO; // Reset buffer params
  1473. dz->total_samps_read -= STEREO;
  1474. dz->samps_left += STEREO;
  1475. sndseekEx(dz->ifd[0],dz->total_samps_read,0); // and Reset position in file
  1476. }
  1477. sampsread_l = dz->ssampsread;
  1478. sampsread_r = dz->ssampsread;
  1479. stereo_pairs_read_l = dz->ssampsread/STEREO;
  1480. stereo_pairs_read_r = stereo_pairs_read_l;
  1481. stereo_pairs_read = stereo_pairs_read_l; // Initially, same samples on both input buffers
  1482. buf_advanced_l = 0;
  1483. buf_advanced_r = 0;
  1484. // NB only one channel of stereo needs to be calcd - other follows BY SYMMETRY
  1485. while(stereo_pairs_read > 0) { // Process continues until BOTH input reads are exhausted
  1486. time = (double)((dz->total_samps_written + c1)/STEREO)/srate;
  1487. if((exit_status = read_values_from_all_existing_brktables(time,dz))< 0)
  1488. return exit_status;
  1489. calcgains(&ch1pos,&pos,&lastspin,&flipped,&movingforward,&leftgain,&rightgain,srate,dz);
  1490. // If either of the input pointers runs out of samples, attempt to read more ....
  1491. // If all left samps read before all right, stereo_pairs_read_l can now be ZERO.
  1492. // In this case, continue to read from (ZEROED) buffer, until right-chan read also reads zero samples .. signalling both reads exhausted
  1493. if((stereo_pairs_read_l == 0 && iposl >= stereo_pairs_buflen) || (stereo_pairs_read_l > 0 && iposl >= stereo_pairs_read_l)) {
  1494. if(buf_advanced_l && (stereo_pairs_read_l != 0)) { // IF left read ALREADY ahead of right-read, and left NOT exhaused, problem
  1495. sprintf(errstr,"Reading samples for 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  1496. return MEMORY_ERROR;
  1497. }
  1498. if(buf_advanced_r) { // If already read into other (right) buffer,
  1499. memcpy((char *)ibufl,(char *)ibufr,(sampsread_r + STEREO) * sizeof(float));
  1500. sampsread_l = sampsread_r; // simply copy input data from one buff to other
  1501. stereo_pairs_read_l = stereo_pairs_read_r; // Reset counters
  1502. buf_advanced_r = 0; // and indicate buffer-R is not read-ahead of buffer-L
  1503. } else { // IF NOT, // Read into l-buffer etc.
  1504. dz->buflen += STEREO; // accomodating possible wrap-around points
  1505. memset((char *)ibufl,0,dz->buflen * sizeof(float));
  1506. if((exit_status = read_samps(ibufl,dz))<0)
  1507. return(exit_status);
  1508. dz->buflen -= STEREO;
  1509. if(dz->ssampsread > dz->buflen) {
  1510. dz->ssampsread -= STEREO;
  1511. dz->total_samps_read -= STEREO;
  1512. dz->samps_left += STEREO;
  1513. sndseekEx(dz->ifd[0],dz->total_samps_read,0);
  1514. }
  1515. sampsread_l = dz->ssampsread;
  1516. stereo_pairs_read_l = sampsread_l/STEREO;
  1517. buf_advanced_l = 1; // and indicate that L-buffer is read-ahead of right buffer
  1518. }
  1519. // stereo_pairs_read set to MAX of reads from left & from right chans (as 1 buffer may be exhausted)
  1520. stereo_pairs_read = max(stereo_pairs_read_l,stereo_pairs_read_r);
  1521. iposl -= stereo_pairs_buflen; // If previous buffer was full, backtrack by buflen lands inside buffer.
  1522. iposl = max(0.0,iposl); // BUT, if previous read reached endoffile, (hence buffer here zeroed & nothing written to it).
  1523. // the baktrak jumps past zerobuf to a -ve val, so just reset to buf start (to read zeros)
  1524. }
  1525. // SIMIL FOR READING RIGHT-CHAN INFO
  1526. if((stereo_pairs_read_r == 0 && iposr >= stereo_pairs_buflen) || (stereo_pairs_read_r > 0 && iposr >= stereo_pairs_read_r)) {
  1527. if(buf_advanced_r && (stereo_pairs_read_r != 0)) {
  1528. sprintf(errstr,"Reading samples for 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  1529. return MEMORY_ERROR;
  1530. }
  1531. if(buf_advanced_l) {
  1532. memcpy((char *)ibufr,(char *)ibufl,(sampsread_l + STEREO) * sizeof(float));
  1533. sampsread_r = sampsread_l;
  1534. stereo_pairs_read_r = stereo_pairs_read_l;
  1535. buf_advanced_l = 0;
  1536. } else {
  1537. dz->buflen += STEREO;
  1538. memset((char *)ibufr,0,dz->buflen * sizeof(float));
  1539. if((exit_status = read_samps(ibufr,dz))<0)
  1540. return(exit_status);
  1541. dz->buflen -= STEREO;
  1542. if(dz->ssampsread > dz->buflen) {
  1543. dz->ssampsread -= STEREO;
  1544. dz->total_samps_read -= STEREO;
  1545. dz->samps_left += STEREO;
  1546. sndseekEx(dz->ifd[0],dz->total_samps_read,0);
  1547. }
  1548. sampsread_r = dz->ssampsread;
  1549. stereo_pairs_read_r = sampsread_r/STEREO;
  1550. buf_advanced_r = 1;
  1551. }
  1552. stereo_pairs_read = max(stereo_pairs_read_l,stereo_pairs_read_r);
  1553. iposr -= stereo_pairs_buflen;
  1554. iposr = max(0.0,iposr);
  1555. }
  1556. if(stereo_pairs_read == 0) // Once BOTH reads get zero samples, we've reached end of both read processes, so quit
  1557. break;
  1558. lo = (int)floor(iposl); // Using doppler pointer on left-chan
  1559. frac = iposl - (double)lo;
  1560. lo *= STEREO; // Find left-chan samples adjacent to pointer
  1561. hi = lo + 2; // and Interp value
  1562. diff = ibufl[hi] - ibufl[lo];
  1563. lval = ibufl[lo] + (diff * frac);
  1564. lo = (int)floor(iposr); // Using doppler pointer on right-chan
  1565. frac = iposr - (double)lo;
  1566. lo *= STEREO;
  1567. lo++; // Find right-chan sample
  1568. hi = lo + 2; // simil
  1569. diff = ibufr[hi] - ibufr[lo];
  1570. rval = ibufr[lo] + (diff * frac);
  1571. if(dz->param[SPNATTEN] > 0.0) { // Atten goes linearly 0->ATTEN->0 as output moves L->C->R
  1572. atten = (1.0 - fabs(pos)) * dz->param[SPNATTEN];
  1573. atten = 1.0 - atten; // So level is multiplied by (1-atten), going from 1->(1-atten)->1 from L->C->R
  1574. leftgain *= atten;
  1575. rightgain *= atten;
  1576. }
  1577. lleftgain = leftgain; // To position left channel in stereo of output , calculate appropriate left and right gain
  1578. lrightgain = rightgain;
  1579. rleftgain = rightgain; // By symmetry, right channel inverts the level of left and right
  1580. rrightgain = leftgain;
  1581. // Differential boost between front and rear
  1582. if(dz->param[SPNBOOST] > 0.0) { // Booster goes linearly 0->BOOST->0 as output moves L->C->R
  1583. boost = (1.0 - fabs(pos)) * dz->param[SPNBOOST];
  1584. boost += 1.0; // Booster becomes a multiplier(divider)
  1585. if(movingforward < 0) { // moving forwards (other channel moving backwards)
  1586. lleftgain *= boost; // Original chan1(left) is moving across front, positioning levels are increased
  1587. lrightgain *= boost;
  1588. rleftgain /= boost; // Original chan2(right) is moving across rear, positioning levels are decreased
  1589. rrightgain /= boost;
  1590. } else {
  1591. lleftgain /= boost; // Original chan1(left) is moving across rear, positioning levels are decrease
  1592. lrightgain /= boost;
  1593. rleftgain *= boost; // Original chan2(right) is moving across front, positioning levels are increased
  1594. rrightgain *= boost;
  1595. }
  1596. }
  1597. obuf[c1] = (float)(obuf[c1] + (lval * lleftgain)); // Orig ch1 signal positioned at new pos, to left and right
  1598. obuf[c2] = (float)(obuf[c2] + (lval * lrightgain));
  1599. obuf[c1] = (float)(obuf[c1] + (rval * rleftgain)); // Orig ch2 signal positioned at new pos, to left and right
  1600. obuf[c2] = (float)(obuf[c2] + (rval * rrightgain));
  1601. c1 += 2;
  1602. c2 += 2; // Advance in output buffer
  1603. // and if it fills up, write to output
  1604. if(c1 >= dz->buflen) {
  1605. if(passno == 0) {
  1606. for(n=0;n<dz->buflen;n++)
  1607. maxsamp = max(maxsamp,fabs(obuf[n]));
  1608. dz->total_samps_written += dz->buflen; // Update to ensure "sampletime" is calculated correctly for sloom display
  1609. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  1610. display_virtual_time(dz->total_samps_written,dz);
  1611. dz->process = SPIN;
  1612. } else {
  1613. if(normaliser < 1.0) {
  1614. for(n=0;n<dz->buflen;n++)
  1615. obuf[n] = (float)(obuf[n] * normaliser);
  1616. }
  1617. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  1618. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1619. return(exit_status);
  1620. dz->process = SPIN;
  1621. }
  1622. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1623. c1 = 0;
  1624. c2 = 1;
  1625. } // Calculate read-insound increment to accomodate doppler pshift
  1626. incrl = dz->pshift_factor * (-dz->param[SPNRATE]) * pos;
  1627. incrl = pow(2.0,incrl); // Convert octaves to frq ratio
  1628. incrr = 2.0 - incrl; // For incrs and decrs to cancel each other in long term, we must have incr2 = 2 - incrl;
  1629. iposl += incrl; // Advance in input sound according to doppler pitchshift on (originally) left edge
  1630. iposr += incrr; // Advance in input sound according to doppler pitchshift on (originally) right edge
  1631. }
  1632. if(c1 > 0) { // Write any residual output
  1633. if(passno == 0) {
  1634. for(n=0;n<c1;n++)
  1635. maxsamp = max(maxsamp,fabs(obuf[n]));
  1636. dz->total_samps_written += c1;
  1637. display_virtual_time(dz->total_samps_written,dz);
  1638. } else {
  1639. if(normaliser < 1.0) {
  1640. for(n=0;n<c1;n++)
  1641. obuf[n] = (float)(obuf[n] * normaliser);
  1642. }
  1643. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  1644. if((exit_status = write_samps(obuf,c1,dz))<0)
  1645. return(exit_status);
  1646. dz->process = SPIN;
  1647. }
  1648. }
  1649. if(passno == 0) {
  1650. if(maxsamp > 0.95)
  1651. normaliser = 0.95/maxsamp;
  1652. else if(maxsamp <= FLTERR) {
  1653. sprintf(errstr,"No significant signal found in source file.\n");
  1654. return DATA_ERROR;
  1655. }
  1656. }
  1657. }
  1658. return FINISHED;
  1659. }
  1660. /******************************** SPINWDOPL ********************************
  1661. *
  1662. * same logic as spindopl, but now output goes to multichan file, and signal goes to a central channel between two orig chans.
  1663. */
  1664. int spinwdopl(dataptr dz)
  1665. {
  1666. int exit_status, passno = 0, flipped = 0, movingforward, buf_advanced_l, buf_advanced_r, ochans = dz->iparam[SPNOCHNS];
  1667. float *ibufl = dz->sampbuf[0], *ibufr = dz->sampbuf[1], *obuf = dz->sampbuf[2];
  1668. double srate = (double)dz->infile->srate, iposl, iposr;
  1669. double ch1pos, normaliser = 1.0, maxsamp = 0.0, time = 0.0, firstspin, lastspin;
  1670. double pos = 0.0, leftgain, lleftgain, rleftgain, rightgain, lrightgain, rrightgain, boost, atten, frac, diff, lval, rval, incrl, incrr;
  1671. int c1, c2, cc, opos, n, obuflen, stereo_pairs_read, stereo_pairs_read_l, stereo_pairs_read_r, lo, hi;
  1672. int sampsread_l, sampsread_r, stereo_pairs_buflen = dz->buflen/STEREO;
  1673. int lchan, rchan, cchan = dz->iparam[SPNOCNTR];
  1674. double boostrange = dz->param[SPNCMAX] - dz->param[SPNCMIN];
  1675. lchan = cchan - 1;
  1676. if(lchan < 1)
  1677. lchan += ochans;
  1678. rchan = cchan + 1;
  1679. if(rchan > ochans)
  1680. rchan -= ochans;
  1681. lchan--; // Convert from 1-N frame to 0to-1 frame for countingt channels
  1682. rchan--;
  1683. cchan--;
  1684. obuflen = (dz->buflen/STEREO) * ochans; // Calc size of output buffer
  1685. if(dz->brksize[SPNRATE]) {
  1686. if((exit_status= read_value_from_brktable(time,SPNRATE,dz))< 0)
  1687. return exit_status;
  1688. }
  1689. firstspin = dz->param[SPNRATE];
  1690. dz->tempsize = (dz->insams[0]/STEREO) * ochans; // For Loom progress-bar: total size of output
  1691. for(passno = 0;passno < 2; passno++) {
  1692. if(passno == 0) {
  1693. fprintf(stdout,"INFO: Assessing output level\n");
  1694. fflush(stdout);
  1695. } else {
  1696. fprintf(stdout,"INFO: Creating output sound\n");
  1697. fflush(stdout);
  1698. }
  1699. dz->total_samps_written = 0;
  1700. display_virtual_time(dz->total_samps_written,dz);
  1701. ch1pos = 0; // Channel 1 starts at beginning of motion-cycle range (0 of 0to1)
  1702. if(firstspin >= 0.0)
  1703. movingforward = 1; // Left image moves backwards (right image moves forwards) - clockwise, viewed from above
  1704. else
  1705. movingforward = -1; // Left image moves forward (right image moves backwards) - anticlockwise, viewed from above
  1706. lastspin = firstspin;
  1707. flipped = 0;
  1708. dz->total_samps_read = 0;
  1709. if((sndseekEx(dz->ifd[0],0,0) < 0)){
  1710. sprintf(errstr,"sndseek failed\n");
  1711. return SYSTEM_ERROR;
  1712. }
  1713. iposl = 0;
  1714. iposr = 0;
  1715. opos = 0;
  1716. c1 = lchan;
  1717. c2 = rchan;
  1718. cc = cchan;
  1719. memset((char *)obuf,0,obuflen * sizeof(float));
  1720. memset((char *)ibufl,0,(dz->buflen + STEREO) * sizeof(float));
  1721. memset((char *)ibufr,0,(dz->buflen + STEREO) * sizeof(float));
  1722. dz->buflen += STEREO; // accomodate wrap-around points
  1723. if((exit_status = read_samps(ibufl,dz))<0)
  1724. return(exit_status);
  1725. memcpy((char *)ibufr,(char *)ibufl,dz->ssampsread * sizeof(float));
  1726. dz->buflen -= STEREO;
  1727. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  1728. dz->ssampsread -= STEREO; // Reset buffer params
  1729. dz->total_samps_read -= STEREO;
  1730. sndseekEx(dz->ifd[0],dz->total_samps_read,0); // and Reset position in file
  1731. }
  1732. sampsread_l = dz->ssampsread;
  1733. sampsread_r = dz->ssampsread;
  1734. stereo_pairs_read_l = dz->ssampsread/STEREO;
  1735. stereo_pairs_read_r = stereo_pairs_read_l;
  1736. stereo_pairs_read = stereo_pairs_read_l; // Initially, same samples on both input buffers
  1737. buf_advanced_l = 0;
  1738. buf_advanced_r = 0;
  1739. // NB only one channel of stereo needs to be calcd - other follows BY SYMMETRY
  1740. while(stereo_pairs_read > 0) {
  1741. time = (double)((dz->total_samps_written + c1)/STEREO)/srate;
  1742. if((exit_status = read_values_from_all_existing_brktables(time,dz))< 0)
  1743. return exit_status;
  1744. calcgains(&ch1pos,&pos,&lastspin,&flipped,&movingforward,&leftgain,&rightgain,srate,dz);
  1745. if((stereo_pairs_read_l == 0 && iposl >= stereo_pairs_buflen) || (stereo_pairs_read_l > 0 && iposl >= stereo_pairs_read_l)) {
  1746. if(buf_advanced_l && (stereo_pairs_read_l != 0)) {
  1747. sprintf(errstr,"Reading samples for 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  1748. return MEMORY_ERROR;
  1749. }
  1750. if(buf_advanced_r) {
  1751. memcpy((char *)ibufl,(char *)ibufr,(sampsread_r + STEREO) * sizeof(float));
  1752. sampsread_l = sampsread_r;
  1753. stereo_pairs_read_l = stereo_pairs_read_r;
  1754. buf_advanced_r = 0;
  1755. } else {
  1756. dz->buflen += STEREO;
  1757. memset((char *)ibufl,0,dz->buflen * sizeof(float));
  1758. if((exit_status = read_samps(ibufl,dz))<0)
  1759. return(exit_status);
  1760. dz->buflen -= STEREO;
  1761. if(dz->ssampsread > dz->buflen) {
  1762. dz->ssampsread -= STEREO;
  1763. dz->total_samps_read -= STEREO;
  1764. sndseekEx(dz->ifd[0],dz->total_samps_read,0);
  1765. }
  1766. sampsread_l = dz->ssampsread;
  1767. stereo_pairs_read_l = sampsread_l/STEREO;
  1768. buf_advanced_l = 1;
  1769. }
  1770. stereo_pairs_read = max(stereo_pairs_read_l,stereo_pairs_read_r);
  1771. iposl -= stereo_pairs_buflen;
  1772. iposl = max(0.0,iposl);
  1773. }
  1774. // SIMIL FOR READING RIGHT-CHAN INFO
  1775. if((stereo_pairs_read_r == 0 && iposr >= stereo_pairs_buflen) || (stereo_pairs_read_r > 0 && iposr >= stereo_pairs_read_r)) {
  1776. if(buf_advanced_r && (stereo_pairs_read_r != 0)) {
  1777. sprintf(errstr,"Reading samples for 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  1778. return MEMORY_ERROR;
  1779. }
  1780. if(buf_advanced_l) {
  1781. memcpy((char *)ibufr,(char *)ibufl,(sampsread_l + STEREO) * sizeof(float));
  1782. sampsread_r = sampsread_l;
  1783. stereo_pairs_read_r = stereo_pairs_read_l;
  1784. buf_advanced_l = 0;
  1785. } else {
  1786. dz->buflen += STEREO;
  1787. memset((char *)ibufr,0,dz->buflen * sizeof(float));
  1788. if((exit_status = read_samps(ibufr,dz))<0)
  1789. return(exit_status);
  1790. dz->buflen -= STEREO;
  1791. if(dz->ssampsread > dz->buflen) {
  1792. dz->ssampsread -= STEREO;
  1793. dz->total_samps_read -= STEREO;
  1794. // dz->samps_left += STEREO;
  1795. sndseekEx(dz->ifd[0],dz->total_samps_read,0);
  1796. }
  1797. sampsread_r = dz->ssampsread;
  1798. stereo_pairs_read_r = sampsread_r/STEREO;
  1799. buf_advanced_r = 1;
  1800. }
  1801. stereo_pairs_read = max(stereo_pairs_read_l,stereo_pairs_read_r);
  1802. iposr -= stereo_pairs_buflen;
  1803. iposr = max(0.0,iposr);
  1804. }
  1805. if(stereo_pairs_read == 0)
  1806. break;
  1807. lo = (int)floor(iposl); // Using doppler pointer on left-chan
  1808. frac = iposl - (double)lo;
  1809. lo *= STEREO; // Find left-chan samples adjacent to pointer
  1810. hi = lo + 2; // and Interp value
  1811. diff = ibufl[hi] - ibufl[lo];
  1812. lval = ibufl[lo] + (diff * frac);
  1813. lo = (int)floor(iposr); // Using doppler pointer on right-chan
  1814. frac = iposr - (double)lo;
  1815. lo *= STEREO;
  1816. lo++; // Find right-chan sample
  1817. hi = lo + 2; // simil
  1818. diff = ibufr[hi] - ibufr[lo];
  1819. rval = ibufr[lo] + (diff * frac);
  1820. if(dz->param[SPNATTEN] > 0.0) { // Atten goes linearly 0->ATTEN->0 as output moves L->C->R
  1821. atten = (1.0 - fabs(pos)) * dz->param[SPNATTEN];
  1822. atten = 1.0 - atten; // So level is multiplied by (1-atten), going from 1->(1-atten)->1 from L->C->R
  1823. leftgain *= atten;
  1824. rightgain *= atten;
  1825. }
  1826. lleftgain = leftgain; // To position left channel in stereo of output , calculate appropriate left and right gain
  1827. lrightgain = rightgain;
  1828. rleftgain = rightgain; // By symmetry, right channel inverts the level of left and right
  1829. rrightgain = leftgain;
  1830. // Differential boost between front and rear
  1831. if(dz->param[SPNBOOST] > 0.0) { // Booster goes linearly 0->BOOST->0 as output moves L->C->R
  1832. boost = (1.0 - fabs(pos)) * dz->param[SPNBOOST];
  1833. boost += 1.0; // Booster becomes a multiplier(divider)
  1834. if(movingforward < 0) { // moving forwards (other channel moving backwards)
  1835. lleftgain *= boost; // Original chan1(left) is moving across front, positioning levels are increased
  1836. lrightgain *= boost;
  1837. rleftgain /= boost; // Original chan2(right) is moving across rear, positioning levels are decreased
  1838. rrightgain /= boost;
  1839. } else {
  1840. lleftgain /= boost; // Original chan1(left) is moving across rear, positioning levels are decrease
  1841. lrightgain /= boost;
  1842. rleftgain *= boost; // Original chan2(right) is moving across front, positioning levels are increased
  1843. rrightgain *= boost;
  1844. }
  1845. }
  1846. obuf[c1] = (float)(obuf[c1] + (lval * lleftgain)); // Orig ch1 signal positioned at new pos, to left and right
  1847. obuf[c2] = (float)(obuf[c2] + (lval * lrightgain));
  1848. obuf[c1] = (float)(obuf[c1] + (rval * rleftgain)); // Orig ch2 signal positioned at new pos, to left and right
  1849. obuf[c2] = (float)(obuf[c2] + (rval * rrightgain));
  1850. boost = (1.0 - fabs(pos)) * boostrange; // Central channel
  1851. boost += dz->param[SPNCMIN];
  1852. obuf[cc] = (float)((lval + rval) * boost); // Gets scaled mono mix of stereo input
  1853. opos += ochans;
  1854. c1 += ochans;
  1855. c2 += ochans;
  1856. cc += ochans;
  1857. if(opos >= obuflen) {
  1858. if(passno == 0) {
  1859. for(n=0;n<obuflen;n++)
  1860. maxsamp = max(maxsamp,fabs(obuf[n]));
  1861. dz->total_samps_written += obuflen; // Update to ensure "time" is calculated correctly
  1862. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  1863. time_display(dz->total_samps_written,dz);
  1864. dz->process = SPIN;
  1865. } else {
  1866. if(normaliser < 1.0) {
  1867. for(n=0;n<obuflen;n++)
  1868. obuf[n] = (float)(obuf[n] * normaliser);
  1869. }
  1870. dz->process = DISTORT_PULSED;
  1871. if((exit_status = write_samps(obuf,obuflen,dz))<0)
  1872. return(exit_status);
  1873. dz->process = SPIN;
  1874. }
  1875. memset((char *)obuf,0,obuflen * sizeof(float));
  1876. opos = 0;
  1877. c1 = lchan;
  1878. c2 = rchan;
  1879. cc = cchan;
  1880. } // Calculate read-insound increment to accomodate doppler pshift
  1881. incrl = dz->pshift_factor * (-dz->param[SPNRATE]) * pos;
  1882. incrl = pow(2.0,incrl); // Convert octaves to frq ratio
  1883. incrr = 2.0 - incrl; // For incrs and decrs to cancel each other in long term, we must have incr2 = 2 - incrl;
  1884. iposl += incrl; // Advance in input sound according to doppler pitchshift on (originally) left edge
  1885. iposr += incrr; // Advance in input sound according to doppler pitchshift on (originally) right edge
  1886. }
  1887. if(opos > 0) {
  1888. if(passno == 0) {
  1889. for(n=0;n<opos;n++)
  1890. maxsamp = max(maxsamp,fabs(obuf[n]));
  1891. dz->process = DISTORT_PULSED;
  1892. display_virtual_time(dz->tempsize,dz);
  1893. dz->process = SPIN;
  1894. } else {
  1895. if(normaliser < 1.0) {
  1896. for(n=0;n<opos;n++)
  1897. obuf[n] = (float)(obuf[n] * normaliser);
  1898. }
  1899. dz->process = DISTORT_PULSED;
  1900. if((exit_status = write_samps(obuf,opos,dz))<0)
  1901. return(exit_status);
  1902. dz->process = SPIN;
  1903. }
  1904. }
  1905. if(passno == 0) {
  1906. if(maxsamp > 0.95)
  1907. normaliser = 0.95/maxsamp;
  1908. else if(maxsamp <= FLTERR) {
  1909. sprintf(errstr,"No significant signal found in source file.\n");
  1910. return DATA_ERROR;
  1911. }
  1912. }
  1913. }
  1914. return FINISHED;
  1915. }
  1916. /******************************** SPINQDOPL ********************************
  1917. *
  1918. * The same logic, with 1 stereo input on chans -1 and +1,and other on -2 and +2, around a cnetre channel.
  1919. */
  1920. int spinqdopl(dataptr dz)
  1921. {
  1922. int exit_status, budge, passno = 0, flipped = 0, movingforward, buf_advanced1_l, buf_advanced1_r, buf_advanced2_l, buf_advanced2_r, ochans = dz->iparam[SPNOCHNS];
  1923. float *ibuf1l = dz->sampbuf[0], *ibuf1r = dz->sampbuf[1], *ibuf2l = dz->sampbuf[2], *ibuf2r = dz->sampbuf[3], *obuf = dz->sampbuf[4];
  1924. double srate = (double)dz->infile->srate, ipos1l, ipos1r, ipos2l, ipos2r;
  1925. double ch1pos, normaliser = 1.0, maxsamp = 0.0, time = 0.0, firstspin, lastspin;
  1926. double pos = 0.0, leftgain, lleftgain, rleftgain, rightgain, lrightgain, rrightgain, boost, atten, frac, diff, lval1, rval1, lval2, rval2, incrl, incrr;
  1927. int c1, c2, cc, c3, c4, opos, n, obuflen;
  1928. int stereo_pairs_read, stereo_pairs_read1, stereo_pairs_read2, stereo_pairs_read1_l, stereo_pairs_read1_r, stereo_pairs_read2_l, stereo_pairs_read2_r;
  1929. int lo, hi, total_samps_read1, total_samps_read2, sampsread1_l, sampsread1_r, sampsread2_l, sampsread2_r, stereo_pairs_buflen = dz->buflen/STEREO;
  1930. int lchan1, rchan1, lchan2, rchan2, cchan = dz->iparam[SPNOCNTR];
  1931. double boostrange = dz->param[SPNCMAX] - dz->param[SPNCMIN];
  1932. lchan1 = cchan - 1;
  1933. if(lchan1 < 1)
  1934. lchan1 += ochans;
  1935. rchan1 = cchan + 1;
  1936. if(rchan1 > ochans)
  1937. rchan1 -= ochans;
  1938. lchan2 = cchan - 2;
  1939. if(lchan2 < 1)
  1940. lchan2 += ochans;
  1941. rchan2 = cchan + 2;
  1942. if(rchan2 > ochans)
  1943. rchan2 -= ochans;
  1944. lchan1--; // Convert from 1-N frame to 0to-1 frame for countingt channels
  1945. rchan1--;
  1946. lchan2--;
  1947. rchan2--;
  1948. cchan--;
  1949. obuflen = (dz->buflen/STEREO) * ochans; // Calc size of output buffer
  1950. if(dz->brksize[SPNRATE]) {
  1951. if((exit_status= read_value_from_brktable(time,SPNRATE,dz))< 0)
  1952. return exit_status;
  1953. }
  1954. firstspin = dz->param[SPNRATE];
  1955. dz->total_samps_written = 0;
  1956. dz->tempsize = (dz->insams[0]/STEREO) * ochans; // For Loom progress-bar: total size of output
  1957. for(passno = 0;passno < 2; passno++) {
  1958. if(passno == 0) {
  1959. fprintf(stdout,"INFO: Assessing output level\n");
  1960. fflush(stdout);
  1961. } else {
  1962. fprintf(stdout,"INFO: Creating output sound\n");
  1963. fflush(stdout);
  1964. }
  1965. dz->total_samps_written = 0;
  1966. display_virtual_time(dz->total_samps_written,dz);
  1967. ch1pos = 0; // Channel 1 starts at beginning of motion-cycle range (0 of 0to1)
  1968. if(firstspin >= 0.0)
  1969. movingforward = 1; // Left image moves backwards (right image moves forwards) - clockwise, viewed from above
  1970. else
  1971. movingforward = -1; // Left image moves forward (right image moves backwards) - anticlockwise, viewed from above
  1972. lastspin = firstspin;
  1973. flipped = 0;
  1974. dz->total_samps_read = 0;
  1975. if((sndseekEx(dz->ifd[0],0,0) < 0)){
  1976. sprintf(errstr,"sndseek failed in input file 1\n");
  1977. return SYSTEM_ERROR;
  1978. }
  1979. if((sndseekEx(dz->ifd[1],0,0) < 0)){
  1980. sprintf(errstr,"sndseek failed in input file 2\n");
  1981. return SYSTEM_ERROR;
  1982. }
  1983. ipos1l = 0; // initialise all buffer pointers
  1984. ipos1r = 0;
  1985. ipos2l = 0;
  1986. ipos2r = 0;
  1987. opos = 0;
  1988. c1 = lchan1;
  1989. c2 = rchan1;
  1990. c3 = lchan2;
  1991. c4 = rchan2;
  1992. cc = cchan; // zero all buffers, including wraparound points
  1993. memset((char *)obuf,0,dz->buflen * sizeof(float));
  1994. memset((char *)ibuf1l,0,(dz->buflen + STEREO) * sizeof(float));
  1995. memset((char *)ibuf1r,0,(dz->buflen + STEREO) * sizeof(float));
  1996. memset((char *)ibuf2l,0,(dz->buflen + STEREO) * sizeof(float));
  1997. memset((char *)ibuf2r,0,(dz->buflen + STEREO) * sizeof(float));
  1998. dz->buflen += STEREO; // accomodate wrap-around points
  1999. memset((char *)ibuf1l,0,dz->buflen * sizeof(float));
  2000. if((dz->ssampsread = fgetfbufEx(ibuf1l, dz->buflen,dz->ifd[0],0)) < 0) {
  2001. sprintf(errstr,"Can't read samples from input soundfile 1.\n");
  2002. return(SYSTEM_ERROR);
  2003. }
  2004. memcpy((char *)ibuf1r,(char *)ibuf1l,dz->ssampsread * sizeof(float));
  2005. dz->buflen -= STEREO;
  2006. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  2007. dz->ssampsread -= STEREO; // Reset buffer params
  2008. sndseekEx(dz->ifd[0],dz->ssampsread,0); // and Reset position in file
  2009. }
  2010. total_samps_read1 = dz->ssampsread;
  2011. sampsread1_l = dz->ssampsread;
  2012. sampsread1_r = dz->ssampsread;
  2013. stereo_pairs_read1_l = dz->ssampsread/STEREO;
  2014. stereo_pairs_read1_r = stereo_pairs_read1_l;
  2015. stereo_pairs_read1 = stereo_pairs_read1_l; // Initially, same samples on both input buffers
  2016. buf_advanced1_l = 0;
  2017. buf_advanced1_r = 0;
  2018. dz->buflen += STEREO; // accomodate wrap-around points
  2019. memset((char *)ibuf2l,0,dz->buflen * sizeof(float));
  2020. if((dz->ssampsread = fgetfbufEx(ibuf2l, dz->buflen,dz->ifd[1],0)) < 0) {
  2021. sprintf(errstr,"Can't read samples from input soundfile 2.\n");
  2022. return(SYSTEM_ERROR);
  2023. }
  2024. memcpy((char *)ibuf2r,(char *)ibuf2l,dz->ssampsread * sizeof(float));
  2025. dz->buflen -= STEREO;
  2026. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  2027. dz->ssampsread -= STEREO; // Reset buffer params
  2028. sndseekEx(dz->ifd[1],dz->ssampsread,0); // and Reset position in file
  2029. }
  2030. total_samps_read2 = dz->ssampsread;
  2031. sampsread2_l = dz->ssampsread;
  2032. sampsread2_r = dz->ssampsread;
  2033. stereo_pairs_read2_l = dz->ssampsread/STEREO;
  2034. stereo_pairs_read2_r = stereo_pairs_read2_l;
  2035. stereo_pairs_read2 = stereo_pairs_read2_l; // Initially, same samples on both input buffers
  2036. buf_advanced2_l = 0;
  2037. buf_advanced2_r = 0;
  2038. stereo_pairs_read = max(stereo_pairs_read1,stereo_pairs_read2);
  2039. // NB only one channel of stereo needs to be calcd - other follows BY SYMMETRY
  2040. while(stereo_pairs_read > 0) {
  2041. time = (double)((dz->total_samps_written + opos)/ochans)/srate; // Time calculated from count of output
  2042. if((exit_status= read_values_from_all_existing_brktables(time,dz))< 0)
  2043. return exit_status;
  2044. calcgains(&ch1pos,&pos,&lastspin,&flipped,&movingforward,&leftgain,&rightgain,srate,dz);
  2045. if((stereo_pairs_read1_l == 0 && ipos1l >= stereo_pairs_buflen) || (stereo_pairs_read1_l > 0 && ipos1l >= stereo_pairs_read1_l)) {
  2046. if(buf_advanced1_l && (stereo_pairs_read1_l != 0)) {
  2047. sprintf(errstr,"Reading samples for 1st sound, 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2048. return MEMORY_ERROR;
  2049. }
  2050. if(buf_advanced1_r) {
  2051. memcpy((char *)ibuf1l,(char *)ibuf1r,(sampsread1_r + STEREO) * sizeof(float));
  2052. sampsread1_l = sampsread1_r;
  2053. stereo_pairs_read1_l = stereo_pairs_read1_r;
  2054. buf_advanced1_r = 0;
  2055. } else {
  2056. dz->buflen += STEREO;
  2057. memset((char *)ibuf1l,0,dz->buflen * sizeof(float));
  2058. if((dz->ssampsread = fgetfbufEx(ibuf1l, dz->buflen,dz->ifd[0],0)) < 0) {
  2059. sprintf(errstr,"Can't read samples from input soundfile 1.\n");
  2060. return(SYSTEM_ERROR);
  2061. }
  2062. dz->buflen -= STEREO;
  2063. budge = 0;
  2064. if(dz->ssampsread > dz->buflen) {
  2065. budge = 1;
  2066. dz->ssampsread -= STEREO;
  2067. }
  2068. total_samps_read1 += dz->ssampsread;
  2069. if(budge)
  2070. sndseekEx(dz->ifd[0],total_samps_read1,0);
  2071. sampsread1_l = dz->ssampsread;
  2072. stereo_pairs_read1_l = sampsread1_l/STEREO;
  2073. buf_advanced1_l = 1;
  2074. }
  2075. stereo_pairs_read1 = max(stereo_pairs_read1_l,stereo_pairs_read1_r);
  2076. ipos1l -= stereo_pairs_buflen;
  2077. ipos1l = max(0.0,ipos1l);
  2078. }
  2079. // SIMIL FOR READING RIGHT-CHAN INFO
  2080. if((stereo_pairs_read1_r == 0 && ipos1r >= stereo_pairs_buflen) || (stereo_pairs_read1_r > 0 && ipos1r >= stereo_pairs_read1_r)) {
  2081. if(buf_advanced1_r && (stereo_pairs_read1_r != 0)) {
  2082. sprintf(errstr,"Reading samples for 1st file, 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2083. return MEMORY_ERROR;
  2084. }
  2085. if(buf_advanced1_l) {
  2086. memcpy((char *)ibuf1r,(char *)ibuf1l,(sampsread1_l + STEREO) * sizeof(float));
  2087. sampsread1_r = sampsread1_l;
  2088. stereo_pairs_read1_r = stereo_pairs_read1_l;
  2089. buf_advanced1_l = 0;
  2090. } else {
  2091. dz->buflen += STEREO;
  2092. memset((char *)ibuf1r,0,dz->buflen * sizeof(float));
  2093. if((dz->ssampsread = fgetfbufEx(ibuf1r, dz->buflen,dz->ifd[0],0)) < 0) {
  2094. sprintf(errstr,"Can't read samples from input soundfile 1.\n");
  2095. return(SYSTEM_ERROR);
  2096. }
  2097. dz->buflen -= STEREO;
  2098. budge = 0;
  2099. if(dz->ssampsread > dz->buflen) {
  2100. dz->ssampsread -= STEREO;
  2101. budge = 1;
  2102. }
  2103. total_samps_read1 += dz->ssampsread;
  2104. if(budge)
  2105. sndseekEx(dz->ifd[0],total_samps_read1,0);
  2106. sampsread1_r = dz->ssampsread;
  2107. stereo_pairs_read1_r = sampsread1_r/STEREO;
  2108. buf_advanced1_r = 1;
  2109. }
  2110. stereo_pairs_read1 = max(stereo_pairs_read1_l,stereo_pairs_read1_r);
  2111. ipos1r -= stereo_pairs_buflen;
  2112. ipos1r = max(0.0,ipos1r);
  2113. }
  2114. // SAME THING FOR 2ND INFILE
  2115. if((stereo_pairs_read2_l == 0 && ipos2l >= stereo_pairs_buflen) || (stereo_pairs_read2_l > 0 && ipos2l >= stereo_pairs_read2_l)) {
  2116. if(buf_advanced2_l && (stereo_pairs_read2_l != 0)) {
  2117. sprintf(errstr,"Reading samples for 2nd sound, 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2118. return MEMORY_ERROR;
  2119. }
  2120. if(buf_advanced2_r) {
  2121. memcpy((char *)ibuf2l,(char *)ibuf2r,(sampsread2_r + STEREO) * sizeof(float));
  2122. sampsread2_l = sampsread2_r;
  2123. stereo_pairs_read2_l = stereo_pairs_read2_r;
  2124. buf_advanced2_r = 0;
  2125. } else {
  2126. dz->buflen += STEREO;
  2127. memset((char *)ibuf2l,0,dz->buflen * sizeof(float));
  2128. if((dz->ssampsread = fgetfbufEx(ibuf2l, dz->buflen,dz->ifd[1],0)) < 0) {
  2129. sprintf(errstr,"Can't read samples from input soundfile 2.\n");
  2130. return(SYSTEM_ERROR);
  2131. }
  2132. dz->buflen -= STEREO;
  2133. budge = 0;
  2134. if(dz->ssampsread > dz->buflen) {
  2135. dz->ssampsread -= STEREO;
  2136. budge = 1;
  2137. }
  2138. total_samps_read2 += dz->ssampsread;
  2139. if(budge)
  2140. sndseekEx(dz->ifd[1],total_samps_read2,0);
  2141. sampsread2_l = dz->ssampsread;
  2142. stereo_pairs_read2_l = sampsread2_l/STEREO;
  2143. buf_advanced2_l = 1;
  2144. }
  2145. stereo_pairs_read2 = max(stereo_pairs_read2_l,stereo_pairs_read2_r);
  2146. ipos2l -= stereo_pairs_buflen;
  2147. ipos2l = max(0.0,ipos2l);
  2148. }
  2149. // SIMIL FOR READING RIGHT-CHAN INFO
  2150. if((stereo_pairs_read2_r == 0 && ipos2r >= stereo_pairs_buflen) || (stereo_pairs_read2_r > 0 && ipos2r >= stereo_pairs_read2_r)) {
  2151. if(buf_advanced2_r && (stereo_pairs_read2_r != 0)) {
  2152. sprintf(errstr,"Reading samples for 2nd file, 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2153. return MEMORY_ERROR;
  2154. }
  2155. if(buf_advanced2_l) {
  2156. memcpy((char *)ibuf2r,(char *)ibuf2l,(sampsread2_l + STEREO) * sizeof(float));
  2157. sampsread2_r = sampsread2_l;
  2158. stereo_pairs_read2_r = stereo_pairs_read2_l;
  2159. buf_advanced2_l = 0;
  2160. } else {
  2161. dz->buflen += STEREO;
  2162. memset((char *)ibuf2r,0,dz->buflen * sizeof(float));
  2163. if((dz->ssampsread = fgetfbufEx(ibuf2r, dz->buflen,dz->ifd[1],0)) < 0) {
  2164. sprintf(errstr,"Can't read samples from input soundfile 2.\n");
  2165. return(SYSTEM_ERROR);
  2166. }
  2167. dz->buflen -= STEREO;
  2168. budge = 0;
  2169. if(dz->ssampsread > dz->buflen) {
  2170. dz->ssampsread -= STEREO;
  2171. budge = 1;
  2172. }
  2173. if(budge)
  2174. total_samps_read2 += dz->ssampsread;
  2175. sndseekEx(dz->ifd[1],total_samps_read2,0);
  2176. total_samps_read2 += dz->ssampsread;
  2177. sampsread2_r = dz->ssampsread;
  2178. stereo_pairs_read2_r = sampsread2_r/STEREO;
  2179. buf_advanced2_r = 1;
  2180. }
  2181. stereo_pairs_read2 = max(stereo_pairs_read2_l,stereo_pairs_read2_r);
  2182. ipos2r -= stereo_pairs_buflen;
  2183. ipos2r = max(0.0,ipos2r);
  2184. }
  2185. stereo_pairs_read = max(stereo_pairs_read1,stereo_pairs_read2);
  2186. if(stereo_pairs_read == 0)
  2187. break;
  2188. lo = (int)floor(ipos1l); // Using doppler pointer on left-chan
  2189. frac = ipos1l - (double)lo;
  2190. lo *= STEREO; // Find left-chan samples adjacent to pointer
  2191. hi = lo + 2; // and Interp value
  2192. diff = ibuf1l[hi] - ibuf1l[lo];
  2193. lval1 = ibuf1l[lo] + (diff * frac);
  2194. lo = (int)floor(ipos1r); // Using doppler pointer on right-chan
  2195. frac = ipos1r - (double)lo;
  2196. lo *= STEREO;
  2197. lo++; // Find right-chan sample
  2198. hi = lo + 2; // simil
  2199. diff = ibuf1r[hi] - ibuf1r[lo];
  2200. rval1 = ibuf1r[lo] + (diff * frac);
  2201. // and for file 2
  2202. lo = (int)floor(ipos2l); // Using doppler pointer on left-chan
  2203. frac = ipos2l - (double)lo;
  2204. lo *= STEREO; // Find left-chan samples adjacent to pointer
  2205. hi = lo + 2; // and Interp value
  2206. diff = ibuf2l[hi] - ibuf2l[lo];
  2207. lval2 = ibuf2l[lo] + (diff * frac);
  2208. lo = (int)floor(ipos2r); // Using doppler pointer on right-chan
  2209. frac = ipos2r - (double)lo;
  2210. lo *= STEREO;
  2211. lo++; // Find right-chan sample
  2212. hi = lo + 2; // simil
  2213. diff = ibuf2r[hi] - ibuf2r[lo];
  2214. rval2 = ibuf2r[lo] + (diff * frac);
  2215. if(dz->param[SPNATTEN] > 0.0) { // Atten goes linearly 0->ATTEN->0 as output moves L->C->R
  2216. atten = (1.0 - fabs(pos)) * dz->param[SPNATTEN];
  2217. atten = 1.0 - atten; // So level is multiplied by (1-atten), going from 1->(1-atten)->1 from L->C->R
  2218. leftgain *= atten;
  2219. rightgain *= atten;
  2220. }
  2221. lleftgain = leftgain; // To position left channel in stereo of output , calculate appropriate left and right gain
  2222. lrightgain = rightgain;
  2223. rleftgain = rightgain; // By symmetry, right channel inverts the level of left and right
  2224. rrightgain = leftgain;
  2225. // Differential boost between front and rear
  2226. if(dz->param[SPNBOOST] > 0.0) { // Booster goes linearly 0->BOOST->0 as output moves L->C->R
  2227. boost = (1.0 - fabs(pos)) * dz->param[SPNBOOST];
  2228. boost += 1.0; // Booster becomes a multiplier(divider)
  2229. if(movingforward < 0) { // moving forwards (other channel moving backwards)
  2230. lleftgain *= boost; // Original chan1(left) is moving across front, positioning levels are increased
  2231. lrightgain *= boost;
  2232. rleftgain /= boost; // Original chan2(right) is moving across rear, positioning levels are decreased
  2233. rrightgain /= boost;
  2234. } else {
  2235. lleftgain /= boost; // Original chan1(left) is moving across rear, positioning levels are decrease
  2236. lrightgain /= boost;
  2237. rleftgain *= boost; // Original chan2(right) is moving across front, positioning levels are increased
  2238. rrightgain *= boost;
  2239. }
  2240. }
  2241. obuf[c1] = (float)(obuf[c1] + (lval1 * lleftgain)); // Orig file1 left signal positioned at new pos, to left and right
  2242. obuf[c2] = (float)(obuf[c2] + (lval1 * lrightgain));
  2243. obuf[c3] = (float)(obuf[c3] + (lval2 * lleftgain)); // Orig file2 left signal positioned at new pos, to left and right
  2244. obuf[c4] = (float)(obuf[c4] + (lval2 * lrightgain));
  2245. obuf[c1] = (float)(obuf[c1] + (rval1 * rleftgain)); // Orig file1 right signal positioned at new pos, to left and right
  2246. obuf[c2] = (float)(obuf[c2] + (rval1 * rrightgain));
  2247. obuf[c3] = (float)(obuf[c3] + (rval2 * rleftgain)); // Orig file2 right signal positioned at new pos, to left and right
  2248. obuf[c4] = (float)(obuf[c4] + (rval2 * rrightgain));
  2249. boost = (1.0 - fabs(pos)) * boostrange; // Central channel
  2250. boost += dz->param[SPNCMIN];
  2251. obuf[cc] = (float)((lval1 + rval1 + lval2 + rval2) * boost); // Gets scaled mono mix of stereo input
  2252. opos += ochans;
  2253. c1 += ochans;
  2254. c2 += ochans;
  2255. c3 += ochans;
  2256. c4 += ochans;
  2257. cc += ochans;
  2258. if(opos >= obuflen) {
  2259. if(passno == 0) {
  2260. for(n=0;n<obuflen;n++)
  2261. maxsamp = max(maxsamp,fabs(obuf[n]));
  2262. dz->total_samps_written += obuflen; // Update to ensure "time" is calculated correctly
  2263. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  2264. time_display(dz->total_samps_written,dz);
  2265. dz->process = SPIN;
  2266. } else {
  2267. if(normaliser < 1.0) {
  2268. for(n=0;n<obuflen;n++)
  2269. obuf[n] = (float)(obuf[n] * normaliser);
  2270. }
  2271. dz->process = DISTORT_PULSED;
  2272. if((exit_status = write_samps(obuf,obuflen,dz))<0)
  2273. return(exit_status);
  2274. dz->process = SPIN;
  2275. }
  2276. memset((char *)obuf,0,obuflen * sizeof(float));
  2277. opos = 0;
  2278. c1 = lchan1;
  2279. c2 = rchan1;
  2280. c3 = lchan2;
  2281. c4 = rchan2;
  2282. cc = cchan;
  2283. } // Calculate read-insound increment to accomodate doppler pshift
  2284. incrl = dz->pshift_factor * (-dz->param[SPNRATE]) * pos;
  2285. incrl = pow(2.0,incrl); // Convert octaves to frq ratio
  2286. incrr = 2.0 - incrl; // For incrs and decrs to cancel each other in long term, we must have incr2 = 2 - incrl;
  2287. ipos1l += incrl; // Advance in input sound according to doppler pitchshift on (originally) left edge
  2288. ipos1r += incrr; // Advance in input sound according to doppler pitchshift on (originally) right edge
  2289. ipos2l += incrl; // and same for other file
  2290. ipos2r += incrr;
  2291. }
  2292. if(opos > 0) {
  2293. if(passno == 0) {
  2294. for(n=0;n<opos;n++)
  2295. maxsamp = max(maxsamp,fabs(obuf[n]));
  2296. dz->process = DISTORT_PULSED;
  2297. display_virtual_time(dz->tempsize,dz);
  2298. dz->process = SPIN;
  2299. } else {
  2300. if(normaliser < 1.0) {
  2301. for(n=0;n<opos;n++)
  2302. obuf[n] = (float)(obuf[n] * normaliser);
  2303. }
  2304. dz->process = DISTORT_PULSED;
  2305. if((exit_status = write_samps(obuf,opos,dz))<0)
  2306. return(exit_status);
  2307. dz->process = SPIN;
  2308. }
  2309. }
  2310. if(passno == 0) {
  2311. if(maxsamp > 0.95)
  2312. normaliser = 0.95/maxsamp;
  2313. else if(maxsamp <= FLTERR) {
  2314. sprintf(errstr,"No significant signal found in source file.\n");
  2315. return DATA_ERROR;
  2316. }
  2317. }
  2318. }
  2319. return FINISHED;
  2320. }
  2321. /******************************** SPINWDOPL2 ********************************
  2322. *
  2323. * SPINWDOPL retains pans L and R edges of sound image between channels C-1 and C+1 (where C is centre channel)
  2324. * complementing it with (variable) extra signal in C.
  2325. * SPINWDOPL2 pans L-edge from chan C-1 to C, then from C to C+1, (and R-edge C+1 ->C then C->C-1)
  2326. * so that signal in centre channel is generated by the Ledge->C or Redge->C pans, directly.
  2327. */
  2328. int spinwdopl2(dataptr dz)
  2329. {
  2330. int exit_status, passno = 0, flipped = 0, movingforward, buf_advanced_l, buf_advanced_r, ochans = dz->iparam[SPNOCHNS];
  2331. float *ibufl = dz->sampbuf[0], *ibufr = dz->sampbuf[1], *obuf = dz->sampbuf[2];
  2332. double srate = (double)dz->infile->srate, iposl, iposr;
  2333. double ch1pos, normaliser = 1.0, maxsamp = 0.0, time = 0.0, firstspin, lastspin;
  2334. double pos = 0.0, leftgain, lleftgain, rleftgain, rightgain, lrightgain, rrightgain, centregain, lcentregain, rcentregain, atten, boost, frac, diff, lval, rval, incrl, incrr;
  2335. int c1, c2, cc, opos, n, obuflen, stereo_pairs_read, stereo_pairs_read_l, stereo_pairs_read_r, lo, hi;
  2336. int sampsread_l, sampsread_r, stereo_pairs_buflen = dz->buflen/STEREO;
  2337. int lchan, rchan, cchan = dz->iparam[SPNOCNTR];
  2338. lchan = cchan - 1;
  2339. if(lchan < 1)
  2340. lchan += ochans;
  2341. rchan = cchan + 1;
  2342. if(rchan > ochans)
  2343. rchan -= ochans;
  2344. lchan--; // Convert from 1-N frame to 0to-1 frame for countingt channels
  2345. rchan--;
  2346. cchan--;
  2347. obuflen = (dz->buflen/STEREO) * ochans; // Calc size of output buffer
  2348. atten = 1.0 - dz->param[SPNATTEN];
  2349. if(dz->brksize[SPNRATE]) {
  2350. if((exit_status= read_value_from_brktable(time,SPNRATE,dz))< 0)
  2351. return exit_status;
  2352. }
  2353. firstspin = dz->param[SPNRATE];
  2354. dz->tempsize = (dz->insams[0]/STEREO) * ochans; // For Loom progress-bar: total size of output
  2355. for(passno = 0;passno < 2; passno++) {
  2356. if(passno == 0) {
  2357. fprintf(stdout,"INFO: Assessing output level\n");
  2358. fflush(stdout);
  2359. } else {
  2360. fprintf(stdout,"INFO: Creating output sound\n");
  2361. fflush(stdout);
  2362. }
  2363. dz->total_samps_written = 0;
  2364. display_virtual_time(dz->total_samps_written,dz);
  2365. ch1pos = 0; // Channel 1 starts at beginning of motion-cycle range (0 of 0to1)
  2366. if(firstspin >= 0.0)
  2367. movingforward = 1; // Left image moves backwards (right image moves forwards) - clockwise, viewed from above
  2368. else
  2369. movingforward = -1; // Left image moves forward (right image moves backwards) - anticlockwise, viewed from above
  2370. lastspin = firstspin;
  2371. flipped = 0;
  2372. dz->total_samps_read = 0;
  2373. // dz->samps_left = dz->insams[0];
  2374. if((sndseekEx(dz->ifd[0],0,0) < 0)){
  2375. sprintf(errstr,"sndseek failed\n");
  2376. return SYSTEM_ERROR;
  2377. }
  2378. iposl = 0;
  2379. iposr = 0;
  2380. opos = 0;
  2381. c1 = lchan;
  2382. c2 = rchan;
  2383. cc = cchan;
  2384. memset((char *)obuf,0,obuflen * sizeof(float));
  2385. memset((char *)ibufl,0,(dz->buflen + STEREO) * sizeof(float));
  2386. memset((char *)ibufr,0,(dz->buflen + STEREO) * sizeof(float));
  2387. dz->buflen += STEREO; // accomodate wrap-around points
  2388. if((exit_status = read_samps(ibufl,dz))<0)
  2389. return(exit_status);
  2390. memcpy((char *)ibufr,(char *)ibufl,dz->ssampsread * sizeof(float));
  2391. dz->buflen -= STEREO;
  2392. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  2393. dz->ssampsread -= STEREO; // Reset buffer params
  2394. dz->total_samps_read -= STEREO;
  2395. // dz->samps_left += STEREO;
  2396. sndseekEx(dz->ifd[0],dz->total_samps_read,0); // and Reset position in file
  2397. }
  2398. sampsread_l = dz->ssampsread;
  2399. sampsread_r = dz->ssampsread;
  2400. stereo_pairs_read_l = dz->ssampsread/STEREO;
  2401. stereo_pairs_read_r = stereo_pairs_read_l;
  2402. stereo_pairs_read = stereo_pairs_read_l; // Initially, same samples on both input buffers
  2403. buf_advanced_l = 0;
  2404. buf_advanced_r = 0;
  2405. // NB only one channel of stereo needs to be calcd - other follows BY SYMMETRY
  2406. while(stereo_pairs_read > 0) {
  2407. time = (double)((dz->total_samps_written + c1)/STEREO)/srate;
  2408. if((exit_status = read_values_from_all_existing_brktables(time,dz))< 0)
  2409. return exit_status;
  2410. calcgains2(&ch1pos,&pos,&lastspin,&flipped,&movingforward,&leftgain,&centregain,&rightgain,srate,dz);
  2411. if((stereo_pairs_read_l == 0 && iposl >= stereo_pairs_buflen) || (stereo_pairs_read_l > 0 && iposl >= stereo_pairs_read_l)) {
  2412. if(buf_advanced_l && (stereo_pairs_read_l != 0)) {
  2413. sprintf(errstr,"Reading samples for 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2414. return MEMORY_ERROR;
  2415. }
  2416. if(buf_advanced_r) {
  2417. memcpy((char *)ibufl,(char *)ibufr,(sampsread_r + STEREO) * sizeof(float));
  2418. sampsread_l = sampsread_r;
  2419. stereo_pairs_read_l = stereo_pairs_read_r;
  2420. buf_advanced_r = 0;
  2421. } else {
  2422. dz->buflen += STEREO;
  2423. memset((char *)ibufl,0,dz->buflen * sizeof(float));
  2424. if((exit_status = read_samps(ibufl,dz))<0)
  2425. return(exit_status);
  2426. dz->buflen -= STEREO;
  2427. if(dz->ssampsread > dz->buflen) {
  2428. dz->ssampsread -= STEREO;
  2429. dz->total_samps_read -= STEREO;
  2430. sndseekEx(dz->ifd[0],dz->total_samps_read,0);
  2431. }
  2432. sampsread_l = dz->ssampsread;
  2433. stereo_pairs_read_l = sampsread_l/STEREO;
  2434. buf_advanced_l = 1;
  2435. }
  2436. stereo_pairs_read = max(stereo_pairs_read_l,stereo_pairs_read_r);
  2437. iposl -= stereo_pairs_buflen;
  2438. iposl = max(0.0,iposl);
  2439. }
  2440. // SIMIL FOR READING RIGHT-CHAN INFO
  2441. if((stereo_pairs_read_r == 0 && iposr >= stereo_pairs_buflen) || (stereo_pairs_read_r > 0 && iposr >= stereo_pairs_read_r)) {
  2442. if(buf_advanced_r && (stereo_pairs_read_r != 0)) {
  2443. sprintf(errstr,"Reading samples for 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2444. return MEMORY_ERROR;
  2445. }
  2446. if(buf_advanced_l) {
  2447. memcpy((char *)ibufr,(char *)ibufl,(sampsread_l + STEREO) * sizeof(float));
  2448. sampsread_r = sampsread_l;
  2449. stereo_pairs_read_r = stereo_pairs_read_l;
  2450. buf_advanced_l = 0;
  2451. } else {
  2452. dz->buflen += STEREO;
  2453. memset((char *)ibufr,0,dz->buflen * sizeof(float));
  2454. if((exit_status = read_samps(ibufr,dz))<0)
  2455. return(exit_status);
  2456. dz->buflen -= STEREO;
  2457. if(dz->ssampsread > dz->buflen) {
  2458. dz->ssampsread -= STEREO;
  2459. dz->total_samps_read -= STEREO;
  2460. sndseekEx(dz->ifd[0],dz->total_samps_read,0);
  2461. }
  2462. sampsread_r = dz->ssampsread;
  2463. stereo_pairs_read_r = sampsread_r/STEREO;
  2464. buf_advanced_r = 1;
  2465. }
  2466. stereo_pairs_read = max(stereo_pairs_read_l,stereo_pairs_read_r);
  2467. iposr -= stereo_pairs_buflen;
  2468. iposr = max(0.0,iposr);
  2469. }
  2470. if(stereo_pairs_read == 0)
  2471. break;
  2472. lo = (int)floor(iposl); // Using doppler pointer on left-chan
  2473. frac = iposl - (double)lo;
  2474. lo *= STEREO; // Find left-chan samples adjacent to pointer
  2475. hi = lo + 2; // and Interp value
  2476. diff = ibufl[hi] - ibufl[lo];
  2477. lval = ibufl[lo] + (diff * frac);
  2478. lo = (int)floor(iposr); // Using doppler pointer on right-chan
  2479. frac = iposr - (double)lo;
  2480. lo *= STEREO;
  2481. lo++; // Find right-chan sample
  2482. hi = lo + 2; // simil
  2483. diff = ibufr[hi] - ibufr[lo];
  2484. rval = ibufr[lo] + (diff * frac);
  2485. lleftgain = leftgain; // Position originally-L-edge by weighting on 3 lspkrs
  2486. lcentregain = centregain;
  2487. lrightgain = rightgain;
  2488. rleftgain = rightgain; // By antisymmetry, do opposite for other edge
  2489. rcentregain = centregain;
  2490. rrightgain = leftgain;
  2491. // Differential boost between front and rear
  2492. if(dz->param[SPNBOOST] > 0.0) { // Booster goes linearly 0->BOOST->0 as output moves L->C->R
  2493. boost = (1.0 - fabs(pos)) * dz->param[SPNBOOST];
  2494. boost += 1.0; // Booster becomes a multiplier(divider)
  2495. if(movingforward < 0) { // moving forwards (other channel moving backwards)
  2496. lcentregain *= boost; // Original chan1(left) is moving across front, positioning levels are increased
  2497. rcentregain /= boost; // Original chan2(right) is moving across rear, positioning levels are decreased
  2498. } else {
  2499. lcentregain /= boost; // Original chan1(left) is moving across rear, positioning levels are decrease
  2500. rcentregain *= boost; // Original chan2(right) is moving across front, positioning levels are increased
  2501. }
  2502. }
  2503. obuf[c1] = (float)(obuf[c1] + (lval * lleftgain)); // Orig ch1 signal contribution , on left and right chans
  2504. obuf[c2] = (float)(obuf[c2] + (lval * lrightgain));
  2505. obuf[c1] = (float)(obuf[c1] + (rval * rleftgain)); // Orig ch2 signal contribution , on left and right chans
  2506. obuf[c2] = (float)(obuf[c2] + (rval * rrightgain));
  2507. obuf[cc] = (float)(((lval * lcentregain) + (rval * rcentregain)) * atten); // Contribution of orig ch1 and ch2 to centre chan level
  2508. obuf[cc] = (float)(obuf[cc] + ((lval + rval) * dz->param[SPNCMIN])); // Add monoed src at min-centre-level
  2509. opos += ochans;
  2510. c1 += ochans;
  2511. c2 += ochans;
  2512. cc += ochans;
  2513. if(opos >= obuflen) {
  2514. if(passno == 0) {
  2515. for(n=0;n<obuflen;n++)
  2516. maxsamp = max(maxsamp,fabs(obuf[n]));
  2517. dz->total_samps_written += obuflen; // Update to ensure "time" is calculated correctly
  2518. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  2519. time_display(dz->total_samps_written,dz);
  2520. dz->process = SPIN;
  2521. } else {
  2522. if(normaliser < 1.0) {
  2523. for(n=0;n<obuflen;n++)
  2524. obuf[n] = (float)(obuf[n] * normaliser);
  2525. }
  2526. dz->process = DISTORT_PULSED;
  2527. if((exit_status = write_samps(obuf,obuflen,dz))<0)
  2528. return(exit_status);
  2529. dz->process = SPIN;
  2530. }
  2531. memset((char *)obuf,0,obuflen * sizeof(float));
  2532. opos = 0;
  2533. c1 = lchan;
  2534. c2 = rchan;
  2535. cc = cchan;
  2536. } // Calculate read-insound increment to accomodate doppler pshift
  2537. incrl = dz->pshift_factor * (-dz->param[SPNRATE]) * pos;
  2538. incrl = pow(2.0,incrl); // Convert octaves to frq ratio
  2539. incrr = 2.0 - incrl; // For incrs and decrs to cancel each other in long term, we must have incr2 = 2 - incrl;
  2540. iposl += incrl; // Advance in input sound according to doppler pitchshift on (originally) left edge
  2541. iposr += incrr; // Advance in input sound according to doppler pitchshift on (originally) right edge
  2542. }
  2543. if(opos > 0) {
  2544. if(passno == 0) {
  2545. for(n=0;n<opos;n++)
  2546. maxsamp = max(maxsamp,fabs(obuf[n]));
  2547. dz->process = DISTORT_PULSED;
  2548. display_virtual_time(dz->tempsize,dz);
  2549. dz->process = SPIN;
  2550. } else {
  2551. if(normaliser < 1.0) {
  2552. for(n=0;n<opos;n++)
  2553. obuf[n] = (float)(obuf[n] * normaliser);
  2554. }
  2555. dz->process = DISTORT_PULSED;
  2556. if((exit_status = write_samps(obuf,opos,dz))<0)
  2557. return(exit_status);
  2558. dz->process = SPIN;
  2559. }
  2560. }
  2561. if(passno == 0) {
  2562. if(maxsamp > 0.95)
  2563. normaliser = 0.95/maxsamp;
  2564. else if(maxsamp <= FLTERR) {
  2565. sprintf(errstr,"No significant signal found in source file.\n");
  2566. return DATA_ERROR;
  2567. }
  2568. }
  2569. }
  2570. return FINISHED;
  2571. }
  2572. /******************************** CALCGAINS2 *****************
  2573. *
  2574. * This function outputs the weightings between L and C channel, and C & RIGHT channels for the item plaaced at "pos" in (L->R) range -1 to 1
  2575. */
  2576. void calcgains2(double *ch1pos,double *pos,double *lastspin,int *flipped,int *movingforward,double *leftgain,double *centregain,double *rightgain,double srate,dataptr dz)
  2577. {
  2578. double cycleincr, lgain, rgain, lrcpos;
  2579. cycleincr = dz->param[SPNRATE]/srate; // How far into the rotation cycle, per sample-group
  2580. *ch1pos += cycleincr;
  2581. // Moving up, from 0 towards 1
  2582. if(cycleincr > 0.0) {
  2583. // If rotate changes direction,
  2584. if(*lastspin < 0.0) // if leaving centre after passing it (flipped), we're now approaching it (!flipped)
  2585. *flipped = !(*flipped); // whereas if approaching centre before passing it (!flipped), we're now leaving it (flipped)
  2586. if(!(*flipped)) { // If we've not previously reached 1/2 way through cycle (travelling up cycle)
  2587. if(*ch1pos > 0.5) { // If we've now reached 1/2 cycle end (Left-channel moved fully from L(-1) to R(1), 1/2 way up (-cos)-table)
  2588. *movingforward = -(*movingforward);// This edge starts to move backwards(if previously moving forwards) (or vice versa),
  2589. *flipped = 1; // and FLAG the fact we've passed the flip-point
  2590. }
  2591. }
  2592. if(*ch1pos > 1.0) { // If we've now reached full cycle end (the end of the (-cos) table, so we're back to start from -1 0 1 0 to -1)
  2593. *flipped = 0; // reset the flip-flag
  2594. *movingforward = -(*movingforward); // This edge starts to move forwards again (if previously backwards) (or vice versa)
  2595. *ch1pos -= 1.0; // reset ch1pos within 0-1 range (0-2PI range of (-cos) table)
  2596. }
  2597. *lastspin = dz->param[SPNRATE]; // Only set "lastspin" when spin is NON-zero, so system remembers last (non-zero) motion direction
  2598. } else if(cycleincr < 0.0) { // Opposite logic, moving down from 1 to 0
  2599. if(*lastspin > 0.0)
  2600. *flipped = !(*flipped);
  2601. if(!(*flipped)) { // If we've not previously reached 1/2 way through cycle (travelling down cycle)
  2602. if(*ch1pos < 0.5) { // If we've now reached 1/2 cycle end (Left-channel moved fully from L(-1) to R(1), 1/2 way down (-cos)-table)
  2603. *movingforward = -(*movingforward); // This edge starts to move backwards(if previously moving forwards) (or vice versa),
  2604. *flipped = 1; // and FLAG the fact we've passed the flip-point
  2605. }
  2606. }
  2607. if(*ch1pos < 0.0) { // If we've now reached full cycle end (the start of the (-cos) table, so we're back to start from -1 0 1 0 to -1)
  2608. *flipped = 0; // reset the flip-flag
  2609. *movingforward = -(*movingforward); // This edge starts to move forwards again (if previously backwards) (or vice versa)
  2610. *ch1pos += 1.0; // reset ch1pos within 0-1 range (0-2PI range of (-cos) table)
  2611. }
  2612. *lastspin = dz->param[SPNRATE];
  2613. }
  2614. *pos = -cos(*ch1pos * TWOPI); // ch1pos ranges from 0 to 1 and recycles, change range to 0 to 2PI
  2615. // -cos goes then ranges (-1 0 1 0 -1 = Left Right Left)
  2616. // pos range = -1 to +1
  2617. lrcpos = *pos * 2.0; // lrcpos Range = -2 to 2
  2618. if(*pos <= 0.0) { // i.e. pos Range = -1 to 0, lrcpos range = -2 to 0
  2619. lrcpos += 1.0; // lrcpos range -1 to + 1
  2620. pancalc(lrcpos,&lgain,&rgain);
  2621. *leftgain = lgain;
  2622. *centregain = rgain;
  2623. *rightgain = 0.0;
  2624. } else { // i.e. pos Range = 0 to 1, lcpos range = 0 to 2
  2625. lrcpos -= 1.0; // lrcpos range = -1 to +1
  2626. pancalc(lrcpos,&lgain,&rgain);
  2627. *leftgain = 0.0;
  2628. *centregain = lgain;
  2629. *rightgain = rgain;
  2630. }
  2631. }
  2632. /******************************** SPINQDOPL2 ********************************
  2633. *
  2634. * The same logic, with 1 stereo input on chans -1 and +1,and other on -2 and +2, around a centre channel.
  2635. */
  2636. int spinqdopl2(dataptr dz)
  2637. {
  2638. int exit_status, budge, passno = 0, flipped = 0, movingforward, buf_advanced1_l, buf_advanced1_r, buf_advanced2_l, buf_advanced2_r, ochans = dz->iparam[SPNOCHNS];
  2639. float *ibuf1l = dz->sampbuf[0], *ibuf1r = dz->sampbuf[1], *ibuf2l = dz->sampbuf[2], *ibuf2r = dz->sampbuf[3], *obuf = dz->sampbuf[4];
  2640. double srate = (double)dz->infile->srate, ipos1l, ipos1r, ipos2l, ipos2r;
  2641. double ch1pos, normaliser = 1.0, maxsamp = 0.0, time = 0.0, firstspin, lastspin;
  2642. double pos = 0.0, leftgain, lleftgain, rleftgain, rightgain, lrightgain, rrightgain, boost, halfboost, atten, frac, diff, lval1, rval1, lval2, rval2, incrl, incrr;
  2643. double centregain,ooleftgain,oileftgain,ocentregain,oirightgain,oorightgain, oval1, oval2;
  2644. double loleftgain, lileftgain, lcentregain, lirightgain, lorightgain, roleftgain, rileftgain, rcentregain, rirightgain, rorightgain;
  2645. int c1, c2, cc, c3, c4, opos, n, obuflen;
  2646. int stereo_pairs_read, stereo_pairs_read1, stereo_pairs_read2, stereo_pairs_read1_l, stereo_pairs_read1_r, stereo_pairs_read2_l, stereo_pairs_read2_r;
  2647. int lo, hi, total_samps_read1, total_samps_read2, sampsread1_l, sampsread1_r, sampsread2_l, sampsread2_r, stereo_pairs_buflen = dz->buflen/STEREO;
  2648. int lchan1, rchan1, lchan2, rchan2, cchan = dz->iparam[SPNOCNTR];
  2649. lchan1 = cchan - 1;
  2650. if(lchan1 < 1)
  2651. lchan1 += ochans;
  2652. rchan1 = cchan + 1;
  2653. if(rchan1 > ochans)
  2654. rchan1 -= ochans;
  2655. lchan2 = cchan - 2;
  2656. if(lchan2 < 1)
  2657. lchan2 += ochans;
  2658. rchan2 = cchan + 2;
  2659. if(rchan2 > ochans)
  2660. rchan2 -= ochans;
  2661. lchan1--; // Convert from 1-N frame to 0to-1 frame for countingt channels
  2662. rchan1--;
  2663. lchan2--;
  2664. rchan2--;
  2665. cchan--;
  2666. obuflen = (dz->buflen/STEREO) * ochans; // Calc size of output buffer
  2667. atten = 1.0 - dz->param[SPNATTEN];
  2668. if(dz->brksize[SPNRATE]) {
  2669. if((exit_status= read_value_from_brktable(time,SPNRATE,dz))< 0)
  2670. return exit_status;
  2671. }
  2672. firstspin = dz->param[SPNRATE];
  2673. dz->total_samps_written = 0;
  2674. dz->tempsize = (dz->insams[0]/STEREO) * ochans; // For Loom progress-bar: total size of output
  2675. for(passno = 0;passno < 2; passno++) {
  2676. if(passno == 0) {
  2677. fprintf(stdout,"INFO: Assessing output level\n");
  2678. fflush(stdout);
  2679. } else {
  2680. fprintf(stdout,"INFO: Creating output sound\n");
  2681. fflush(stdout);
  2682. }
  2683. dz->total_samps_written = 0;
  2684. display_virtual_time(dz->total_samps_written,dz);
  2685. ch1pos = 0; // Channel 1 starts at beginning of motion-cycle range (0 of 0to1)
  2686. if(firstspin >= 0.0)
  2687. movingforward = 1; // Left image moves backwards (right image moves forwards) - clockwise, viewed from above
  2688. else
  2689. movingforward = -1; // Left image moves forward (right image moves backwards) - anticlockwise, viewed from above
  2690. lastspin = firstspin;
  2691. flipped = 0;
  2692. dz->total_samps_read = 0;
  2693. if((sndseekEx(dz->ifd[0],0,0) < 0)){
  2694. sprintf(errstr,"sndseek failed in input file 1\n");
  2695. return SYSTEM_ERROR;
  2696. }
  2697. if((sndseekEx(dz->ifd[1],0,0) < 0)){
  2698. sprintf(errstr,"sndseek failed in input file 2\n");
  2699. return SYSTEM_ERROR;
  2700. }
  2701. ipos1l = 0; // initialise all buffer pointers
  2702. ipos1r = 0;
  2703. ipos2l = 0;
  2704. ipos2r = 0;
  2705. opos = 0;
  2706. c1 = lchan1;
  2707. c2 = rchan1;
  2708. c3 = lchan2;
  2709. c4 = rchan2;
  2710. cc = cchan; // zero all buffers, including wraparound points
  2711. memset((char *)obuf,0,dz->buflen * sizeof(float));
  2712. memset((char *)ibuf1l,0,(dz->buflen + STEREO) * sizeof(float));
  2713. memset((char *)ibuf1r,0,(dz->buflen + STEREO) * sizeof(float));
  2714. memset((char *)ibuf2l,0,(dz->buflen + STEREO) * sizeof(float));
  2715. memset((char *)ibuf2r,0,(dz->buflen + STEREO) * sizeof(float));
  2716. dz->buflen += STEREO; // accomodate wrap-around points
  2717. if((dz->ssampsread = fgetfbufEx(ibuf1l, dz->buflen,dz->ifd[0],0)) < 0) {
  2718. sprintf(errstr,"Can't read samples from input soundfile 1.\n");
  2719. return(SYSTEM_ERROR);
  2720. }
  2721. memcpy((char *)ibuf1r,(char *)ibuf1l,dz->ssampsread * sizeof(float));
  2722. dz->buflen -= STEREO;
  2723. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  2724. dz->ssampsread -= STEREO; // Reset buffer params
  2725. sndseekEx(dz->ifd[0],dz->ssampsread,0); // and Reset position in file
  2726. }
  2727. total_samps_read1 = dz->ssampsread;
  2728. sampsread1_l = dz->ssampsread;
  2729. sampsread1_r = dz->ssampsread;
  2730. stereo_pairs_read1_l = dz->ssampsread/STEREO;
  2731. stereo_pairs_read1_r = stereo_pairs_read1_l;
  2732. stereo_pairs_read1 = stereo_pairs_read1_l; // Initially, same samples on both input buffers
  2733. buf_advanced1_l = 0;
  2734. buf_advanced1_r = 0;
  2735. dz->buflen += STEREO; // accomodate wrap-around points
  2736. if((dz->ssampsread = fgetfbufEx(ibuf2l, dz->buflen,dz->ifd[1],0)) < 0) {
  2737. sprintf(errstr,"Can't read samples from input soundfile 2.\n");
  2738. return(SYSTEM_ERROR);
  2739. }
  2740. memcpy((char *)ibuf2r,(char *)ibuf2l,dz->ssampsread * sizeof(float));
  2741. dz->buflen -= STEREO;
  2742. if(dz->ssampsread > dz->buflen) { // IF wraparound points read
  2743. dz->ssampsread -= STEREO; // Reset buffer params
  2744. sndseekEx(dz->ifd[1],dz->ssampsread,0); // and Reset position in file
  2745. }
  2746. total_samps_read2 = dz->ssampsread;
  2747. sampsread2_l = dz->ssampsread;
  2748. sampsread2_r = dz->ssampsread;
  2749. stereo_pairs_read2_l = dz->ssampsread/STEREO;
  2750. stereo_pairs_read2_r = stereo_pairs_read2_l;
  2751. stereo_pairs_read2 = stereo_pairs_read2_l; // Initially, same samples on both input buffers
  2752. buf_advanced2_l = 0;
  2753. buf_advanced2_r = 0;
  2754. stereo_pairs_read = max(stereo_pairs_read1,stereo_pairs_read2);
  2755. // NB only one channel of stereo needs to be calcd - other follows BY SYMMETRY
  2756. while(stereo_pairs_read > 0) {
  2757. time = (double)((dz->total_samps_written + opos)/ochans)/srate; // Time calculated from count of output
  2758. if((exit_status= read_values_from_all_existing_brktables(time,dz))< 0)
  2759. return exit_status;
  2760. calcgains3(&ch1pos,&pos,&lastspin,&flipped,&movingforward,&leftgain,&centregain,&rightgain,&ooleftgain,&oileftgain,&ocentregain,&oirightgain,&oorightgain,srate,dz);
  2761. if((stereo_pairs_read1_l == 0 && ipos1l >= stereo_pairs_buflen) || (stereo_pairs_read1_l > 0 && ipos1l >= stereo_pairs_read1_l)) {
  2762. if(buf_advanced1_l && (stereo_pairs_read1_l != 0)) {
  2763. sprintf(errstr,"Reading samples for 1st sound, 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2764. return MEMORY_ERROR;
  2765. }
  2766. if(buf_advanced1_r) {
  2767. memcpy((char *)ibuf1l,(char *)ibuf1r,(sampsread1_r + STEREO) * sizeof(float));
  2768. sampsread1_l = sampsread1_r;
  2769. stereo_pairs_read1_l = stereo_pairs_read1_r;
  2770. buf_advanced1_r = 0;
  2771. } else {
  2772. dz->buflen += STEREO;
  2773. memset((char *)ibuf1l,0,dz->buflen * sizeof(float));
  2774. if((dz->ssampsread = fgetfbufEx(ibuf1l, dz->buflen,dz->ifd[0],0)) < 0) {
  2775. sprintf(errstr,"Can't read samples from input soundfile 1.\n");
  2776. return(SYSTEM_ERROR);
  2777. }
  2778. dz->buflen -= STEREO;
  2779. budge = 0;
  2780. if(dz->ssampsread > dz->buflen) {
  2781. budge = 1;
  2782. dz->ssampsread -= STEREO;
  2783. }
  2784. total_samps_read1 += dz->ssampsread;
  2785. if(budge)
  2786. sndseekEx(dz->ifd[0],total_samps_read1,0);
  2787. sampsread1_l = dz->ssampsread;
  2788. stereo_pairs_read1_l = sampsread1_l/STEREO;
  2789. buf_advanced1_l = 1;
  2790. }
  2791. stereo_pairs_read1 = max(stereo_pairs_read1_l,stereo_pairs_read1_r);
  2792. ipos1l -= stereo_pairs_buflen;
  2793. ipos1l = max(0.0,ipos1l);
  2794. }
  2795. // SIMIL FOR READING RIGHT-CHAN INFO
  2796. if((stereo_pairs_read1_r == 0 && ipos1r >= stereo_pairs_buflen) || (stereo_pairs_read1_r > 0 && ipos1r >= stereo_pairs_read1_r)) {
  2797. if(buf_advanced1_r && (stereo_pairs_read1_r != 0)) {
  2798. sprintf(errstr,"Reading samples for 1st file, 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2799. return MEMORY_ERROR;
  2800. }
  2801. if(buf_advanced1_l) {
  2802. memcpy((char *)ibuf1r,(char *)ibuf1l,(sampsread1_l + STEREO) * sizeof(float));
  2803. sampsread1_r = sampsread1_l;
  2804. stereo_pairs_read1_r = stereo_pairs_read1_l;
  2805. buf_advanced1_l = 0;
  2806. } else {
  2807. dz->buflen += STEREO;
  2808. memset((char *)ibuf1r,0,dz->buflen * sizeof(float));
  2809. if((dz->ssampsread = fgetfbufEx(ibuf1r, dz->buflen,dz->ifd[0],0)) < 0) {
  2810. sprintf(errstr,"Can't read samples from input soundfile 1.\n");
  2811. return(SYSTEM_ERROR);
  2812. }
  2813. dz->buflen -= STEREO;
  2814. budge = 0;
  2815. if(dz->ssampsread > dz->buflen) {
  2816. dz->ssampsread -= STEREO;
  2817. budge = 1;
  2818. }
  2819. total_samps_read1 += dz->ssampsread;
  2820. if(budge)
  2821. sndseekEx(dz->ifd[0],total_samps_read1,0);
  2822. sampsread1_r = dz->ssampsread;
  2823. stereo_pairs_read1_r = sampsread1_r/STEREO;
  2824. buf_advanced1_r = 1;
  2825. }
  2826. stereo_pairs_read1 = max(stereo_pairs_read1_l,stereo_pairs_read1_r);
  2827. ipos1r -= stereo_pairs_buflen;
  2828. ipos1r = max(0.0,ipos1r);
  2829. }
  2830. // SAME THING FOR 2ND INFILE
  2831. if((stereo_pairs_read2_l == 0 && ipos2l >= stereo_pairs_buflen) || (stereo_pairs_read2_l > 0 && ipos2l >= stereo_pairs_read2_l)) {
  2832. if(buf_advanced2_l && (stereo_pairs_read2_l != 0)) {
  2833. sprintf(errstr,"Reading samples for 2nd sound, 1st image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2834. return MEMORY_ERROR;
  2835. }
  2836. if(buf_advanced2_r) {
  2837. memcpy((char *)ibuf2l,(char *)ibuf2r,(sampsread2_r + STEREO) * sizeof(float));
  2838. sampsread2_l = sampsread2_r;
  2839. stereo_pairs_read2_l = stereo_pairs_read2_r;
  2840. buf_advanced2_r = 0;
  2841. } else {
  2842. dz->buflen += STEREO;
  2843. memset((char *)ibuf2l,0,dz->buflen * sizeof(float));
  2844. if((dz->ssampsread = fgetfbufEx(ibuf2l, dz->buflen,dz->ifd[1],0)) < 0) {
  2845. sprintf(errstr,"Can't read samples from input soundfile 2.\n");
  2846. return(SYSTEM_ERROR);
  2847. }
  2848. dz->buflen -= STEREO;
  2849. budge = 0;
  2850. if(dz->ssampsread > dz->buflen) {
  2851. dz->ssampsread -= STEREO;
  2852. budge = 1;
  2853. }
  2854. total_samps_read2 += dz->ssampsread;
  2855. if(budge)
  2856. sndseekEx(dz->ifd[1],total_samps_read2,0);
  2857. sampsread2_l = dz->ssampsread;
  2858. stereo_pairs_read2_l = sampsread2_l/STEREO;
  2859. buf_advanced2_l = 1;
  2860. }
  2861. stereo_pairs_read2 = max(stereo_pairs_read2_l,stereo_pairs_read2_r);
  2862. ipos2l -= stereo_pairs_buflen;
  2863. ipos2l = max(0.0,ipos2l);
  2864. }
  2865. // SIMIL FOR READING RIGHT-CHAN INFO
  2866. if((stereo_pairs_read2_r == 0 && ipos2r >= stereo_pairs_buflen) || (stereo_pairs_read2_r > 0 && ipos2r >= stereo_pairs_read2_r)) {
  2867. if(buf_advanced2_r && (stereo_pairs_read2_r != 0)) {
  2868. sprintf(errstr,"Reading samples for 2nd file, 2nd image-edge exceeds other by > buffer length: CANNOT PROCEED\n");
  2869. return MEMORY_ERROR;
  2870. }
  2871. if(buf_advanced2_l) {
  2872. memcpy((char *)ibuf2r,(char *)ibuf2l,(sampsread2_l + STEREO) * sizeof(float));
  2873. sampsread2_r = sampsread2_l;
  2874. stereo_pairs_read2_r = stereo_pairs_read2_l;
  2875. buf_advanced2_l = 0;
  2876. } else {
  2877. dz->buflen += STEREO;
  2878. memset((char *)ibuf2r,0,dz->buflen * sizeof(float));
  2879. if((dz->ssampsread = fgetfbufEx(ibuf2r, dz->buflen,dz->ifd[1],0)) < 0) {
  2880. sprintf(errstr,"Can't read samples from input soundfile 2.\n");
  2881. return(SYSTEM_ERROR);
  2882. }
  2883. dz->buflen -= STEREO;
  2884. budge = 0;
  2885. if(dz->ssampsread > dz->buflen) {
  2886. dz->ssampsread -= STEREO;
  2887. budge = 1;
  2888. }
  2889. total_samps_read2 += dz->ssampsread;
  2890. if(budge)
  2891. sndseekEx(dz->ifd[1],total_samps_read2,0);
  2892. total_samps_read2 += dz->ssampsread;
  2893. sampsread2_r = dz->ssampsread;
  2894. stereo_pairs_read2_r = sampsread2_r/STEREO;
  2895. buf_advanced2_r = 1;
  2896. }
  2897. stereo_pairs_read2 = max(stereo_pairs_read2_l,stereo_pairs_read2_r);
  2898. ipos2r -= stereo_pairs_buflen;
  2899. ipos2r = max(0.0,ipos2r);
  2900. }
  2901. stereo_pairs_read = max(stereo_pairs_read1,stereo_pairs_read2);
  2902. if(stereo_pairs_read == 0)
  2903. break;
  2904. lo = (int)floor(ipos1l); // Using doppler pointer on left-chan
  2905. frac = ipos1l - (double)lo;
  2906. lo *= STEREO; // Find left-chan samples adjacent to pointer
  2907. hi = lo + 2; // and Interp value
  2908. diff = ibuf1l[hi] - ibuf1l[lo];
  2909. lval1 = ibuf1l[lo] + (diff * frac);
  2910. lo = (int)floor(ipos1r); // Using doppler pointer on right-chan
  2911. frac = ipos1r - (double)lo;
  2912. lo *= STEREO;
  2913. lo++; // Find right-chan sample
  2914. hi = lo + 2; // simil
  2915. diff = ibuf1r[hi] - ibuf1r[lo];
  2916. rval1 = ibuf1r[lo] + (diff * frac);
  2917. // and for file 2
  2918. lo = (int)floor(ipos2l); // Using doppler pointer on left-chan
  2919. frac = ipos2l - (double)lo;
  2920. lo *= STEREO; // Find left-chan samples adjacent to pointer
  2921. hi = lo + 2; // and Interp value
  2922. diff = ibuf2l[hi] - ibuf2l[lo];
  2923. lval2 = ibuf2l[lo] + (diff * frac);
  2924. lo = (int)floor(ipos2r); // Using doppler pointer on right-chan
  2925. frac = ipos2r - (double)lo;
  2926. lo *= STEREO;
  2927. lo++; // Find right-chan sample
  2928. hi = lo + 2; // simil
  2929. diff = ibuf2r[hi] - ibuf2r[lo];
  2930. rval2 = ibuf2r[lo] + (diff * frac);
  2931. // FOR THE INNER SOUND
  2932. lleftgain = leftgain; // Position originally-L-edge by weighting on 3 lspkrs
  2933. lcentregain = centregain;
  2934. lrightgain = rightgain;
  2935. rleftgain = rightgain; // By antisymmetry, do opposite for other edge
  2936. rcentregain = centregain;
  2937. rrightgain = leftgain;
  2938. // Differential boost between front and rear
  2939. if(dz->param[SPNBOOST] > 0.0) { // Booster goes linearly 0->BOOST->0 as output moves L->C->R
  2940. boost = (1.0 - fabs(pos)) * dz->param[SPNBOOST];
  2941. boost += 1.0; // Booster becomes a multiplier(divider)
  2942. if(movingforward < 0) { // moving forwards (other channel moving backwards)
  2943. lcentregain *= boost; // Original chan1(left) is moving across front, positioning levels are increased
  2944. rcentregain /= boost; // Original chan2(right) is moving across rear, positioning levels are decreased
  2945. } else {
  2946. lcentregain /= boost; // Original chan1(left) is moving across rear, positioning levels are decrease
  2947. rcentregain *= boost; // Original chan2(right) is moving across front, positioning levels are increased
  2948. }
  2949. }
  2950. obuf[c1] = (float)(obuf[c1] + (lval1 * lleftgain)); // Orig ch1 signal contribution , on left and right chans
  2951. obuf[c2] = (float)(obuf[c2] + (lval1 * lrightgain));
  2952. obuf[c1] = (float)(obuf[c1] + (rval1 * rleftgain)); // Orig ch2 signal contribution , on left and right chans
  2953. obuf[c2] = (float)(obuf[c2] + (rval1 * rrightgain));
  2954. oval1 = (float)(((lval1 * lcentregain) + (rval1 * rcentregain)) * atten); // Contribution of orig ch1 and ch2 to centre chan level
  2955. oval1 += (lval1 + rval1) * dz->param[SPNCMIN]; // Add monoed src at min-centre-level
  2956. obuf[cc] = (float)(obuf[cc] + oval1);
  2957. // FOR THE OUTER SOUND
  2958. loleftgain = ooleftgain; // Weightings on the 5 loudspkrs, of the orig-LEFT-edge of image
  2959. lileftgain = oileftgain;
  2960. lcentregain = ocentregain;
  2961. lirightgain = oirightgain;
  2962. lorightgain = oorightgain;
  2963. roleftgain = oorightgain; // by anti-symmetry, Weightings for the orig-RIGHT-edge of image
  2964. rileftgain = oirightgain;
  2965. rcentregain = ocentregain;
  2966. rirightgain = oileftgain;
  2967. rorightgain = ooleftgain;
  2968. // Differential boost between front and rear
  2969. if(dz->param[SPNBOOST] > 0.0) { // Booster goes linearly 0->BOOST->0 as output moves L->C->R
  2970. boost = (1.0 - fabs(pos)) * dz->param[SPNBOOST];
  2971. boost += 1.0; // Booster becomes a multiplier(divider)
  2972. halfboost = boost/2.0;
  2973. if(movingforward < 0) { // moving forwards (other channel moving backwards)
  2974. lcentregain *= boost; // Original chan1(left) is moving across front, positioning levels are increased
  2975. lileftgain *= halfboost;
  2976. lirightgain *= halfboost;
  2977. rcentregain /= boost; // Original chan2(right) is moving across rear, positioning levels are decreased
  2978. rileftgain /= halfboost;
  2979. rirightgain /= halfboost;
  2980. } else {
  2981. lcentregain /= boost; // Original chan1(left) is moving across rear, positioning levels are decrease
  2982. lileftgain /= halfboost;
  2983. lirightgain /= halfboost;
  2984. rcentregain *= boost; // Original chan2(right) is moving across front, positioning levels are increased
  2985. rileftgain *= halfboost;
  2986. rirightgain *= halfboost;
  2987. }
  2988. } // Orig L-edge signal contribution , on all 5 chans
  2989. obuf[c3] = (float)(obuf[c3] + (lval2 * loleftgain)); // Left outer chan
  2990. obuf[c1] = (float)(obuf[c1] + (lval2 * lileftgain)); // Left inner chan
  2991. obuf[c2] = (float)(obuf[c2] + (lval2 * lirightgain)); // Right inner chan
  2992. obuf[c4] = (float)(obuf[c4] + (lval2 * lorightgain)); // Right outer chan
  2993. obuf[c3] = (float)(obuf[c3] + (rval2 * roleftgain)); // Orig R-edge signal contribution , on all 5 chans
  2994. obuf[c1] = (float)(obuf[c1] + (rval2 * rileftgain));
  2995. obuf[c2] = (float)(obuf[c2] + (rval2 * rirightgain));
  2996. obuf[c4] = (float)(obuf[c4] + (rval2 * rorightgain));
  2997. oval2 = ((lval2 * lcentregain) + (rval2 * rcentregain)) * atten; // Contribution of orig ch1 and ch2 (outer) snd to centre chan level
  2998. oval2 += (lval2 + rval2) * dz->param[SPNCMIN]; // Add monoed src at min-centre-level
  2999. obuf[cc] = (float)(obuf[cc] + oval2);
  3000. opos += ochans;
  3001. c1 += ochans;
  3002. c2 += ochans;
  3003. c3 += ochans;
  3004. c4 += ochans;
  3005. cc += ochans;
  3006. if(opos >= obuflen) {
  3007. if(passno == 0) {
  3008. for(n=0;n<obuflen;n++)
  3009. maxsamp = max(maxsamp,fabs(obuf[n]));
  3010. dz->total_samps_written += obuflen; // Update to ensure "time" is calculated correctly
  3011. dz->process = DISTORT_PULSED; // Forces correct progress-bar display on Loom
  3012. time_display(dz->total_samps_written,dz);
  3013. dz->process = SPIN;
  3014. } else {
  3015. if(normaliser < 1.0) {
  3016. for(n=0;n<obuflen;n++)
  3017. obuf[n] = (float)(obuf[n] * normaliser);
  3018. }
  3019. dz->process = DISTORT_PULSED;
  3020. if((exit_status = write_samps(obuf,obuflen,dz))<0)
  3021. return(exit_status);
  3022. dz->process = SPIN;
  3023. }
  3024. memset((char *)obuf,0,obuflen * sizeof(float));
  3025. opos = 0;
  3026. c1 = lchan1;
  3027. c2 = rchan1;
  3028. c3 = lchan2;
  3029. c4 = rchan2;
  3030. cc = cchan;
  3031. } // Calculate read-insound increment to accomodate doppler pshift
  3032. incrl = dz->pshift_factor * (-dz->param[SPNRATE]) * pos;
  3033. incrl = pow(2.0,incrl); // Convert octaves to frq ratio
  3034. incrr = 2.0 - incrl; // For incrs and decrs to cancel each other in long term, we must have incr2 = 2 - incrl;
  3035. ipos1l += incrl; // Advance in input sound according to doppler pitchshift on (originally) left edge
  3036. ipos1r += incrr; // Advance in input sound according to doppler pitchshift on (originally) right edge
  3037. ipos2l += incrl; // and same for other file
  3038. ipos2r += incrr;
  3039. }
  3040. if(opos > 0) {
  3041. if(passno == 0) {
  3042. for(n=0;n<opos;n++)
  3043. maxsamp = max(maxsamp,fabs(obuf[n]));
  3044. dz->process = DISTORT_PULSED;
  3045. display_virtual_time(dz->tempsize,dz);
  3046. dz->process = SPIN;
  3047. } else {
  3048. if(normaliser < 1.0) {
  3049. for(n=0;n<opos;n++)
  3050. obuf[n] = (float)(obuf[n] * normaliser);
  3051. }
  3052. dz->process = DISTORT_PULSED;
  3053. if((exit_status = write_samps(obuf,opos,dz))<0)
  3054. return(exit_status);
  3055. dz->process = SPIN;
  3056. }
  3057. }
  3058. if(passno == 0) {
  3059. if(maxsamp > 0.95)
  3060. normaliser = 0.95/maxsamp;
  3061. else if(maxsamp <= FLTERR) {
  3062. sprintf(errstr,"No significant signal found in source file.\n");
  3063. return DATA_ERROR;
  3064. }
  3065. }
  3066. }
  3067. return FINISHED;
  3068. }
  3069. /******************************** CALCGAINS3 *******************************
  3070. *
  3071. * This function outputs the weightings between L and C channel, and C & RIGHT channels for the item plaaced at "pos" in (L->R) range -1 to 1
  3072. */
  3073. void calcgains3(double *ch1pos,double *pos,double *lastspin,int *flipped,int *movingforward,double *leftgain,double *centregain,double *rightgain,
  3074. double *ooleftgain, double *oileftgain, double *ocentregain, double *oirightgain, double *oorightgain, double srate,dataptr dz)
  3075. {
  3076. double cycleincr, lgain, rgain, lrcpos, olrcpos;
  3077. cycleincr = dz->param[SPNRATE]/srate; // How far into the rotation cycle, per sample-group
  3078. *ch1pos += cycleincr;
  3079. // Moving up, from 0 towards 1
  3080. if(cycleincr > 0.0) {
  3081. // If rotate changes direction,
  3082. if(*lastspin < 0.0) // if leaving centre after passing it (flipped), we're now approaching it (!flipped)
  3083. *flipped = !(*flipped); // whereas if approaching centre before passing it (!flipped), we're now leaving it (flipped)
  3084. if(!(*flipped)) { // If we've not previously reached 1/2 way through cycle (travelling up cycle)
  3085. if(*ch1pos > 0.5) { // If we've now reached 1/2 cycle end (Left-channel moved fully from L(-1) to R(1), 1/2 way up (-cos)-table)
  3086. *movingforward = -(*movingforward);// This edge starts to move backwards(if previously moving forwards) (or vice versa),
  3087. *flipped = 1; // and FLAG the fact we've passed the flip-point
  3088. }
  3089. }
  3090. if(*ch1pos > 1.0) { // If we've now reached full cycle end (the end of the (-cos) table, so we're back to start from -1 0 1 0 to -1)
  3091. *flipped = 0; // reset the flip-flag
  3092. *movingforward = -(*movingforward); // This edge starts to move forwards again (if previously backwards) (or vice versa)
  3093. *ch1pos -= 1.0; // reset ch1pos within 0-1 range (0-2PI range of (-cos) table)
  3094. }
  3095. *lastspin = dz->param[SPNRATE]; // Only set "lastspin" when spin is NON-zero, so system remembers last (non-zero) motion direction
  3096. } else if(cycleincr < 0.0) { // Opposite logic, moving down from 1 to 0
  3097. if(*lastspin > 0.0)
  3098. *flipped = !(*flipped);
  3099. if(!(*flipped)) { // If we've not previously reached 1/2 way through cycle (travelling down cycle)
  3100. if(*ch1pos < 0.5) { // If we've now reached 1/2 cycle end (Left-channel moved fully from L(-1) to R(1), 1/2 way down (-cos)-table)
  3101. *movingforward = -(*movingforward); // This edge starts to move backwards(if previously moving forwards) (or vice versa),
  3102. *flipped = 1; // and FLAG the fact we've passed the flip-point
  3103. }
  3104. }
  3105. if(*ch1pos < 0.0) { // If we've now reached full cycle end (the start of the (-cos) table, so we're back to start from -1 0 1 0 to -1)
  3106. *flipped = 0; // reset the flip-flag
  3107. *movingforward = -(*movingforward); // This edge starts to move forwards again (if previously backwards) (or vice versa)
  3108. *ch1pos += 1.0; // reset ch1pos within 0-1 range (0-2PI range of (-cos) table)
  3109. }
  3110. *lastspin = dz->param[SPNRATE];
  3111. }
  3112. *pos = -cos(*ch1pos * TWOPI); // ch1pos ranges from 0 to 1 and recycles, change range to 0 to 2PI
  3113. // -cos goes then ranges (-1 0 1 0 -1 = Left Right Left)
  3114. // pos range = -1 to +1
  3115. lrcpos = *pos * 2.0; // lrcpos Range = -2 to 2
  3116. if(*pos <= 0.0) { // i.e. pos Range = -1 to 0, lrcpos range = -2 to 0
  3117. lrcpos += 1.0; // lrcpos range -1 to + 1
  3118. pancalc(lrcpos,&lgain,&rgain);
  3119. *leftgain = lgain;
  3120. *centregain = rgain;
  3121. *rightgain = 0.0;
  3122. } else { // i.e. pos Range = 0 to 1, lcpos range = 0 to 2
  3123. lrcpos -= 1.0; // lrcpos range = -1 to +1
  3124. pancalc(lrcpos,&lgain,&rgain);
  3125. *leftgain = 0.0;
  3126. *centregain = lgain;
  3127. *rightgain = rgain;
  3128. }
  3129. olrcpos = *pos * 4.0; // olrcpos Range = -4 to 4
  3130. if(*pos <= -0.5) { // i.e. pos Range = -1 to -0.5, olrcpos range = -4 to -2
  3131. olrcpos += 3.0; // olrcpos range -1 to + 1
  3132. pancalc(olrcpos,&lgain,&rgain);
  3133. *ooleftgain = lgain;
  3134. *oileftgain = rgain;
  3135. *ocentregain = 0.0;
  3136. *oirightgain = 0.0;
  3137. *oorightgain = 0.0;
  3138. } else if(*pos <= 0.0) { // i.e. pos Range = -0.5 to 0, olcpos range = -2 to 0
  3139. olrcpos += 1.0; // olrcpos range = -1 to +1
  3140. pancalc(olrcpos,&lgain,&rgain);
  3141. *ooleftgain = 0.0;
  3142. *oileftgain = lgain;
  3143. *ocentregain = rgain;
  3144. *oirightgain = 0.0;
  3145. *oorightgain = 0.0;
  3146. } else if(*pos <= 0.5) { // i.e. pos Range = 0 to 0.5, olcpos range = 0 to 2
  3147. olrcpos -= 1.0; // olrcpos range = -1 to +1
  3148. pancalc(olrcpos,&lgain,&rgain);
  3149. *ooleftgain = 0.0;
  3150. *oileftgain = 0.0;
  3151. *ocentregain = lgain;
  3152. *oirightgain = rgain;
  3153. *oorightgain = 0.0;
  3154. } else { // i.e. pos Range = 0.5 to 1, olcpos range = 2 to 4
  3155. olrcpos -= 3.0; // olrcpos range = -1 to +1
  3156. pancalc(olrcpos,&lgain,&rgain);
  3157. *ooleftgain = 0.0;
  3158. *oileftgain = 0.0;
  3159. *ocentregain = 0.0;
  3160. *oirightgain = lgain;
  3161. *oorightgain = rgain;
  3162. }
  3163. }