spin.c 161 KB

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