fofex.c 161 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091
  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. /*
  22. * INPUT MUST BE MONO
  23. * & use PTOBRK to create the pitcb brkpoint file with no-SIG markers
  24. */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <structures.h>
  28. #include <tkglobals.h>
  29. #include <pnames.h>
  30. #include <filetype.h>
  31. #include <processno.h>
  32. #include <modeno.h>
  33. #include <logic.h>
  34. #include <globcon.h>
  35. #include <cdpmain.h>
  36. #include <math.h>
  37. #include <mixxcon.h>
  38. #include <osbind.h>
  39. #include <standalone.h>
  40. #include <ctype.h>
  41. #include <sfsys.h>
  42. #include <string.h>
  43. #include <srates.h>
  44. //#if defined unix || defined __GNUC__
  45. #define round(x) lround((x))
  46. //#endif
  47. #ifndef HUGE
  48. #define HUGE 3.40282347e+38F
  49. #endif
  50. char errstr[2400];
  51. int anal_infiles = 1;
  52. int sloom = 0;
  53. int sloombatch = 0;
  54. const char* cdp_version = "7.1.0";
  55. #define WINDIV (6.0)
  56. #define PITCHERROR (1.5)
  57. #define ALMOST_OCT (1.9)
  58. /* windows are three times smaller than the pitch-cycle */
  59. #define FOF_NORM_LEVEL (0.9)
  60. //CDP LIB REPLACEMENTS
  61. static int setup_fofex_application(dataptr dz);
  62. static int get_fofex_exclude_data(char *filename,dataptr dz);
  63. static int check_fofex_param_validity_and_consistency(dataptr dz);
  64. static int create_fofex_sndbufs(dataptr dz);
  65. static int get_fofbank_info(char *filename,dataptr dz);
  66. static int setup_fofex_param_ranges_and_defaults(dataptr dz);
  67. static int fofexex(dataptr dz);
  68. static int fofexco(dataptr dz);
  69. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  70. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  71. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
  72. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  73. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  74. static int establish_application(dataptr dz);
  75. static int initialise_vflags(dataptr dz);
  76. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  77. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  78. static int mark_parameter_types(dataptr dz,aplptr ap);
  79. static int assign_file_data_storage(int infilecnt,dataptr dz);
  80. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  81. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  82. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  83. static int get_the_mode_from_cmdline(char *str,dataptr dz);
  84. static int create_pitchsteps_semitone_info(double lomidi,double himidi,int **pitchstep,int *outcnt,double srate);
  85. static void smooth_oct_glitches(dataptr dz);
  86. static int establish_normalisers(int unitlen, dataptr dz);
  87. static int remove_zero_signal_areas(int *outsegs,int *outcnt,dataptr dz);
  88. static int remove_outofrange_fofs(int *outsegs,int *outcnt,dataptr dz);
  89. static int remove_lolevel_fofs(int *outsegs,int *outcnt,dataptr dz);
  90. static int extract_pitch_dependent_env_from_sndfile(int minwsize,int k,int *maxwsize,dataptr dz);
  91. static float getmaxsampr(int startsamp, int sampcnt,float *buffer);
  92. static int get_min_wsize(int *minwsize,int k,dataptr dz);
  93. static int find_min_energy_downward_zero_crossing_point
  94. (int *n,int *trofpnt,int trofpntcnt,double *scanarray,int *cutcnt,int *cut,int cutstart,dataptr dz);
  95. static int read_validpitch_wsize_in_samps_from_brktable(double thistime,int kk,dataptr dz);
  96. static int next_zero_cross(int here,dataptr dz);
  97. static int previous_zero_cross(int here,int last,dataptr dz);
  98. static int get_envelope_troughs(int *trofpnt,int *trofpntcnt,int envcnt,dataptr dz);
  99. static int triangulate_env(int *here,int *there,int ideal_place,float *buf);
  100. static int count_zerocrossings(int here,int there,float *buf);
  101. static int mark_cut(int *cutcnt,int *cut,int localpeakcnt,double *startarray,int here,int there,
  102. int startsamp,int first_downcross,double starttime,int msg,dataptr dz);
  103. static int find_the_local_peaks(int *here,int *there,float *buf,int *n,int trofpntcnt,int *trofpnt,
  104. int *startsamp,int *endsamp,int losamp, int *cut, int cutcnt, double *localpeak, double *scanarray,
  105. int *localpeakcnt,int *first_downcross,dataptr dz);
  106. static int smooth_cuts(int *cut,int *cutcnt,int cutstart,dataptr dz);
  107. static int auto_correlate(int start,int *at,int end,int realend,int minlen,double pitchseg,int kk,dataptr dz);
  108. static double autocorrelate(int n,int m,float *buf);
  109. static int next_down_zcross(int here,int hibound,float *buf);
  110. static int last_down_zcross(int here,int lobound,float *buf);
  111. static int handle_the_special_data(int *cmdlinecnt,char ***cmdline,dataptr dz);
  112. static int setup_the_special_data_ranges(int mode,int srate,double duration,double nyquist,int wlength,int channels,aplptr ap);
  113. #define TESTFOFS 1
  114. /**************************************** MAIN *********************************************/
  115. int main(int argc,char *argv[])
  116. {
  117. int exit_status;
  118. dataptr dz = NULL;
  119. char **cmdline;
  120. int cmdlinecnt;
  121. int n;
  122. //aplptr ap;
  123. int is_launched = FALSE;
  124. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  125. fprintf(stdout,"%s\n",cdp_version);
  126. fflush(stdout);
  127. return 0;
  128. }
  129. /* CHECK FOR SOUNDLOOM */
  130. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  131. sloom = 0;
  132. sloombatch = 1;
  133. }
  134. if(sflinit("cdp")){
  135. sfperror("cdp: initialisation\n");
  136. return(FAILED);
  137. }
  138. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  139. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  140. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  141. return(FAILED);
  142. }
  143. if(!sloom) {
  144. if(argc == 1) {
  145. usage1();
  146. return(FAILED);
  147. } else if(argc == 2) {
  148. usage2(argv[1]);
  149. return(FAILED);
  150. }
  151. }
  152. if(!sloom) {
  153. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  154. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  155. return(FAILED);
  156. }
  157. cmdline = argv;
  158. cmdlinecnt = argc;
  159. if((get_the_process_no(argv[0],dz))<0)
  160. return(FAILED);
  161. cmdline++;
  162. cmdlinecnt--;
  163. if(dz->process == FOFEX_CO) {
  164. dz->maxmode = 8;
  165. } else {
  166. dz->maxmode = 3;
  167. }
  168. if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
  169. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  170. return(exit_status);
  171. }
  172. cmdline++;
  173. cmdlinecnt--;
  174. // setup_particular_application =
  175. if((exit_status = setup_fofex_application(dz))<0) {
  176. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  177. return(FAILED);
  178. }
  179. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  180. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  181. return(FAILED);
  182. }
  183. } else {
  184. //parse_TK_data() =
  185. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  186. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  187. return(exit_status);
  188. }
  189. }
  190. //ap = dz->application;
  191. // parse_infile_and_hone_type() =
  192. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  193. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  194. return(FAILED);
  195. }
  196. // setup_param_ranges_and_defaults() =
  197. if((exit_status = setup_fofex_param_ranges_and_defaults(dz))<0) {
  198. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  199. return(FAILED);
  200. }
  201. // open_first_infile CDP LIB
  202. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  203. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  204. return(FAILED);
  205. }
  206. cmdlinecnt--;
  207. cmdline++;
  208. if(dz->process == FOFEX_CO) {
  209. if((exit_status = sndgetprop(dz->ifd[0],"is a fofbank file",(char *) &(dz->itemcnt),sizeof(int))) < 0) {
  210. sprintf(errstr,"Input file is not a FOFbank file\n");
  211. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  212. return(FAILED);
  213. }
  214. dz->descriptor_samps = dz->itemcnt;
  215. }
  216. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
  217. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  218. return(FAILED);
  219. }
  220. dz->itemcnt = 0;
  221. if((exit_status = handle_the_special_data(&cmdlinecnt,&cmdline,dz))<0) {
  222. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  223. return(FAILED);
  224. }
  225. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  226. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  227. return(FAILED);
  228. }
  229. // check_param_validity_and_consistency....
  230. if((dz->process != FOFEX_CO) || (dz->mode != FOF_MEASURE)) {
  231. if((exit_status = check_fofex_param_validity_and_consistency(dz))<0) {
  232. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  233. return(FAILED);
  234. }
  235. }
  236. is_launched = TRUE;
  237. switch(dz->process) {
  238. case(FOFEX_EX):
  239. dz->bufcnt = 2;
  240. break;
  241. case(FOFEX_CO):
  242. if(dz->mode == FOF_MEASURE)
  243. dz->bufcnt = 1;
  244. else
  245. dz->bufcnt = 3;
  246. break;
  247. }
  248. if((dz->sampbuf = (float **)malloc(sizeof(float *) * (dz->bufcnt+1)))==NULL) {
  249. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers.\n");
  250. return(MEMORY_ERROR);
  251. }
  252. if((dz->sbufptr = (float **)malloc(sizeof(float *) * dz->bufcnt))==NULL) {
  253. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffer pointers.\n");
  254. return(MEMORY_ERROR);
  255. }
  256. for(n = 0;n <dz->bufcnt; n++)
  257. dz->sampbuf[n] = dz->sbufptr[n] = (float *)0;
  258. dz->sampbuf[n] = (float *)0;
  259. if((exit_status = create_fofex_sndbufs(dz))<0) {
  260. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  261. return(FAILED);
  262. }
  263. //param_preprocess() redundant
  264. //spec_process_file =
  265. switch(dz->process) {
  266. case(FOFEX_EX):
  267. if((exit_status = fofexex(dz))<0) {
  268. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  269. return(FAILED);
  270. }
  271. if(dz->mode == 0) {
  272. if(sndputprop(dz->ofd,"is a fofbank file", (char *)&(dz->itemcnt), sizeof(int)) < 0){
  273. sprintf(errstr,"Failure to write FOFbank property\n");
  274. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  275. return(FAILED);
  276. }
  277. }
  278. break;
  279. case(FOFEX_CO):
  280. if((exit_status = fofexco(dz))<0) {
  281. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  282. return(FAILED);
  283. }
  284. break;
  285. }
  286. if((exit_status = complete_output(dz))<0) { // CDP LIB
  287. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  288. return(FAILED);
  289. }
  290. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  291. free(dz);
  292. return(SUCCEEDED);
  293. }
  294. /**************************************************/
  295. /* GENERAL FUNCTIONS, REPLACING CDP LIB FUNCTIONS */
  296. /**************************************************/
  297. /****************************** SET_PARAM_DATA *********************************/
  298. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  299. {
  300. ap->special_data = (char)special_data;
  301. ap->param_cnt = (char)paramcnt;
  302. ap->max_param_cnt = (char)maxparamcnt;
  303. if(ap->max_param_cnt>0) {
  304. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  305. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  306. return(MEMORY_ERROR);
  307. }
  308. strcpy(ap->param_list,paramlist);
  309. }
  310. return(FINISHED);
  311. }
  312. /****************************** SET_VFLGS *********************************/
  313. int set_vflgs
  314. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  315. {
  316. ap->option_cnt = (char) optcnt; /*RWD added cast */
  317. if(optcnt) {
  318. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  319. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  320. return(MEMORY_ERROR);
  321. }
  322. strcpy(ap->option_list,optlist);
  323. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  324. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  325. return(MEMORY_ERROR);
  326. }
  327. strcpy(ap->option_flags,optflags);
  328. }
  329. ap->vflag_cnt = (char) vflagcnt;
  330. ap->variant_param_cnt = (char) vparamcnt;
  331. if(vflagcnt) {
  332. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  333. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  334. return(MEMORY_ERROR);
  335. }
  336. strcpy(ap->variant_list,varlist);
  337. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  338. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  339. return(MEMORY_ERROR);
  340. }
  341. strcpy(ap->variant_flags,varflags);
  342. }
  343. return(FINISHED);
  344. }
  345. /***************************** APPLICATION_INIT **************************/
  346. int application_init(dataptr dz)
  347. {
  348. int exit_status;
  349. int storage_cnt;
  350. int tipc, brkcnt;
  351. aplptr ap = dz->application;
  352. brkcnt = 10;
  353. if(ap->vflag_cnt>0)
  354. initialise_vflags(dz);
  355. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  356. ap->total_input_param_cnt = (char)tipc;
  357. if(tipc>0) {
  358. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  359. return(exit_status);
  360. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  361. return(exit_status);
  362. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  363. return(exit_status);
  364. }
  365. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  366. return(exit_status);
  367. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  368. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  369. return(exit_status);
  370. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  371. return(exit_status);
  372. }
  373. if((exit_status = mark_parameter_types(dz,ap))<0)
  374. return(exit_status);
  375. // establish_infile_constants() replaced by
  376. dz->infilecnt = 1;
  377. if((exit_status = setup_internal_arrays_and_array_pointers(dz))<0)
  378. return(exit_status);
  379. //establish_bufptrs_and_extra_buffers():
  380. return(FINISHED);
  381. }
  382. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  383. /* RWD mallo changed to calloc; helps debug verison run as release! */
  384. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  385. {
  386. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  387. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  388. return(MEMORY_ERROR);
  389. }
  390. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  391. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  392. return(MEMORY_ERROR);
  393. }
  394. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  395. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  396. return(MEMORY_ERROR);
  397. }
  398. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  399. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  400. return(MEMORY_ERROR);
  401. }
  402. return(FINISHED);
  403. }
  404. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  405. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  406. {
  407. int n;
  408. for(n=0;n<storage_cnt;n++) {
  409. dz->is_int[n] = (char)0;
  410. dz->no_brk[n] = (char)0;
  411. }
  412. return(FINISHED);
  413. }
  414. /***************************** MARK_PARAMETER_TYPES **************************/
  415. int mark_parameter_types(dataptr dz,aplptr ap)
  416. {
  417. int n, m; /* PARAMS */
  418. for(n=0;n<ap->max_param_cnt;n++) {
  419. switch(ap->param_list[n]) {
  420. case('0'): break; /* dz->is_active[n] = 0 is default */
  421. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  422. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  423. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  424. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  425. default:
  426. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  427. return(PROGRAM_ERROR);
  428. }
  429. } /* OPTIONS */
  430. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  431. switch(ap->option_list[n]) {
  432. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  433. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  434. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  435. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  436. default:
  437. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  438. return(PROGRAM_ERROR);
  439. }
  440. } /* VARIANTS */
  441. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  442. switch(ap->variant_list[n]) {
  443. case('0'): break;
  444. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  445. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  446. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  447. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  448. default:
  449. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  450. return(PROGRAM_ERROR);
  451. }
  452. } /* INTERNAL */
  453. for(n=0,
  454. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  455. switch(ap->internal_param_list[n]) {
  456. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  457. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  458. case('d'): dz->no_brk[m] = (char)1; break;
  459. default:
  460. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  461. return(PROGRAM_ERROR);
  462. }
  463. }
  464. return(FINISHED);
  465. }
  466. /************************ HANDLE_THE_OUTFILE *********************/
  467. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
  468. {
  469. int exit_status, innamelen;
  470. char *filename = (*cmdline)[0], *p, othername[200];
  471. if(filename[0]=='-' && filename[1]=='f') {
  472. dz->floatsam_output = 1;
  473. dz->true_outfile_stype = SAMP_FLOAT;
  474. filename+= 2;
  475. }
  476. if(!sloom) {
  477. if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
  478. sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
  479. return(DATA_ERROR);
  480. }
  481. }
  482. strcpy(dz->outfilename,filename);
  483. if((dz->process == FOFEX_EX) && (dz->mode == 2)) {
  484. strcpy(dz->outfilename,filename);
  485. p = dz->outfilename;
  486. while(*p != ENDOFSTR) {
  487. if(*p == '.') {
  488. *p = ENDOFSTR;
  489. break;
  490. }
  491. p++;
  492. }
  493. if(sloom) { /* Store name without numeric index */
  494. innamelen = strlen(dz->outfilename);
  495. p = dz->outfilename + innamelen;
  496. p--;
  497. *p = ENDOFSTR;
  498. }
  499. if(dz->wordstor!=NULL)
  500. free_wordstors(dz);
  501. dz->all_words = 0;
  502. if((exit_status = store_filename(dz->outfilename,dz))<0)
  503. return exit_status;
  504. } else {
  505. if((exit_status = create_sized_outfile(filename,dz))<0)
  506. return(exit_status);
  507. if((dz->process == FOFEX_EX) && (dz->mode == 0)) {
  508. if(sloom) {
  509. strcpy(othername,"cdptest1");
  510. } else {
  511. if(!strcmp(filename,"cdptest0.wav")) { // FILE ARRIVES FROM SLOOM BUT AS CMDLINE FORMAT
  512. strcpy(othername,"cdptest1.txt");
  513. } else {
  514. strcpy(othername,filename);
  515. p = othername + strlen(othername) - 1;
  516. while(p > othername) {
  517. if(!strcmp(p,"."))
  518. break;
  519. p--;
  520. }
  521. if(p > othername)
  522. *p = ENDOFSTR;
  523. strcat(othername,".txt");
  524. }
  525. }
  526. if((dz->fp = fopen(othername,"w"))==NULL) {
  527. sprintf(errstr,"Cannot open file %s to write fofbank info data.\n",othername);
  528. return(DATA_ERROR);
  529. }
  530. }
  531. }
  532. (*cmdline)++;
  533. (*cmdlinecnt)--;
  534. return(FINISHED);
  535. }
  536. /***************************** ESTABLISH_APPLICATION **************************/
  537. int establish_application(dataptr dz)
  538. {
  539. aplptr ap;
  540. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  541. sprintf(errstr,"establish_application()\n");
  542. return(MEMORY_ERROR);
  543. }
  544. ap = dz->application;
  545. memset((char *)ap,0,sizeof(struct applic));
  546. return(FINISHED);
  547. }
  548. /************************* INITIALISE_VFLAGS *************************/
  549. int initialise_vflags(dataptr dz)
  550. {
  551. int n;
  552. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  553. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  554. return(MEMORY_ERROR);
  555. }
  556. for(n=0;n<dz->application->vflag_cnt;n++)
  557. dz->vflag[n] = FALSE;
  558. return FINISHED;
  559. }
  560. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  561. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  562. {
  563. int n;
  564. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  565. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  566. return(MEMORY_ERROR);
  567. }
  568. for(n=0;n<tipc;n++)
  569. ap->default_val[n] = 0.0;
  570. return(FINISHED);
  571. }
  572. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  573. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  574. {
  575. int n;
  576. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  577. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  578. return(MEMORY_ERROR);
  579. }
  580. for(n=0;n<tipc;n++)
  581. dz->is_active[n] = (char)0;
  582. return(FINISHED);
  583. }
  584. /****************************** SET_LEGAL_INTERNALPARAM_STRUCTURE *********************************/
  585. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  586. {
  587. return(FINISHED); // DUMMY TO SATISFY LIB
  588. }
  589. /************************* SETUP_FOFEX_APPLICATION *******************/
  590. int setup_fofex_application(dataptr dz)
  591. {
  592. int exit_status;
  593. aplptr ap;
  594. if((exit_status = establish_application(dz))<0) // GLOBAL
  595. return(FAILED);
  596. ap = dz->application;
  597. // SEE parstruct FOR EXPLANATION of next 2 functions
  598. if(dz->process == FOFEX_EX) {
  599. switch(dz->mode) {
  600. case(0):
  601. case(2):
  602. if((exit_status = set_param_data(ap,FOFEX_EXCLUDES ,3,3,"Ddi" ))<0)
  603. return(FAILED);
  604. if((exit_status = set_vflgs(ap,"",0,"","w",1,0,"0"))<0)
  605. return(FAILED);
  606. break;
  607. case(1):
  608. if((exit_status = set_param_data(ap,0 ,3,3,"Ddi" ))<0)
  609. return(FAILED);
  610. if((exit_status = set_vflgs(ap,"",0,"","w",1,0,"0"))<0)
  611. return(FAILED);
  612. break;
  613. }
  614. } else {
  615. switch(dz->mode) {
  616. case(FOF_SINGLE):
  617. if((exit_status = set_param_data(ap,FOFBANK_INFO ,10,4,"DDdi000000" ))<0)
  618. return(FAILED);
  619. if((exit_status = set_vflgs(ap,"",0,"","",0,0,""))<0)
  620. return(FAILED);
  621. break;
  622. case(FOF_SUM):
  623. case(FOF_LOSUM):
  624. case(FOF_MIDSUM):
  625. case(FOF_HISUM):
  626. if((exit_status = set_param_data(ap,FOFBANK_INFO ,10,3,"DDd0000000" ))<0)
  627. return(FAILED);
  628. if((exit_status = set_vflgs(ap,"",0,"","n",1,0,"0"))<0)
  629. return(FAILED);
  630. break;
  631. case(FOF_LOHI):
  632. if((exit_status = set_param_data(ap,FOFBANK_INFO ,10,7,"DDdiidd000" ))<0)
  633. return(FAILED);
  634. if((exit_status = set_vflgs(ap,"",0,"","n",1,0,"0"))<0)
  635. return(FAILED);
  636. break;
  637. case(FOF_TRIPLE):
  638. if((exit_status = set_param_data(ap,FOFBANK_INFO ,10,10,"DDdiiidddd" ))<0)
  639. return(FAILED);
  640. if((exit_status = set_vflgs(ap,"",0,"","n",1,0,"0"))<0)
  641. return(FAILED);
  642. break;
  643. case(FOF_MEASURE):
  644. if((exit_status = set_param_data(ap,0 ,10,0,"0000000000" ))<0)
  645. return(FAILED);
  646. if((exit_status = set_vflgs(ap,"",0,"","",0,0,""))<0)
  647. return(FAILED);
  648. break;
  649. }
  650. }
  651. // set_legal_infile_structure -->
  652. dz->has_otherfile = FALSE;
  653. // assign_process_logic -->
  654. dz->input_data_type = SNDFILES_ONLY;
  655. if(dz->process == FOFEX_CO && dz->mode == FOF_MEASURE) {
  656. dz->process_type = TO_TEXTFILE;
  657. dz->outfiletype = TEXTFILE_OUT;
  658. } else if(dz->process == FOFEX_EX && dz->mode == 2) {
  659. dz->process_type = OTHER_PROCESS;
  660. dz->outfiletype = NO_OUTPUTFILE;
  661. } else {
  662. dz->process_type = UNEQUAL_SNDFILE;
  663. dz->outfiletype = SNDFILE_OUT;
  664. }
  665. return application_init(dz); //GLOBAL
  666. }
  667. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  668. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  669. {
  670. int n;
  671. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  672. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  673. return(MEMORY_ERROR);
  674. }
  675. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  676. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  677. return(MEMORY_ERROR);
  678. }
  679. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  680. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  681. return(MEMORY_ERROR);
  682. }
  683. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  684. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  685. return(MEMORY_ERROR);
  686. }
  687. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  688. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  689. return(MEMORY_ERROR);
  690. }
  691. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  692. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  693. return(MEMORY_ERROR);
  694. }
  695. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  696. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  697. return(MEMORY_ERROR);
  698. }
  699. for(n=0;n<brkcnt;n++) {
  700. dz->brk[n] = NULL;
  701. dz->brkptr[n] = NULL;
  702. dz->brkinit[n] = 0;
  703. dz->brksize[n] = 0;
  704. }
  705. return(FINISHED);
  706. }
  707. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  708. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  709. {
  710. int exit_status;
  711. infileptr infile_info;
  712. if(!sloom) {
  713. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  714. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  715. return(MEMORY_ERROR);
  716. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  717. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  718. return(PROGRAM_ERROR);
  719. } else if(infile_info->filetype != SNDFILE) {
  720. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  721. return(DATA_ERROR);
  722. } else if(infile_info->channels != 1) {
  723. sprintf(errstr,"File %s is not of correct type (must be mono)\n",cmdline[0]);
  724. return(DATA_ERROR);
  725. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  726. sprintf(errstr,"Failed to copy file parsing information\n");
  727. return(PROGRAM_ERROR);
  728. }
  729. free(infile_info);
  730. }
  731. return(FINISHED);
  732. }
  733. /********************************* PARSE_SLOOM_DATA *********************************/
  734. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  735. {
  736. int exit_status;
  737. int cnt = 1, infilecnt;
  738. int filesize, insams, inbrksize;
  739. double dummy;
  740. int true_cnt = 0;
  741. //aplptr ap;
  742. while(cnt<=PRE_CMDLINE_DATACNT) {
  743. if(cnt > argc) {
  744. sprintf(errstr,"Insufficient data sent from TK\n");
  745. return(DATA_ERROR);
  746. }
  747. switch(cnt) {
  748. case(1):
  749. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  750. sprintf(errstr,"Cannot read process no. sent from TK\n");
  751. return(DATA_ERROR);
  752. }
  753. break;
  754. case(2):
  755. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  756. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  757. return(DATA_ERROR);
  758. }
  759. if(dz->mode > 0)
  760. dz->mode--;
  761. //setup_particular_application() =
  762. if((exit_status = setup_fofex_application(dz))<0)
  763. return(exit_status);
  764. //ap = dz->application;
  765. break;
  766. case(3):
  767. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  768. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  769. return(DATA_ERROR);
  770. }
  771. if(infilecnt < 1) {
  772. true_cnt = cnt + 1;
  773. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  774. }
  775. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  776. return(exit_status);
  777. break;
  778. case(INPUT_FILETYPE+4):
  779. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  780. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  781. return(DATA_ERROR);
  782. }
  783. break;
  784. case(INPUT_FILESIZE+4):
  785. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  786. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  787. return(DATA_ERROR);
  788. }
  789. dz->insams[0] = filesize;
  790. break;
  791. case(INPUT_INSAMS+4):
  792. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  793. sprintf(errstr,"Cannot read insams sent from TK\n");
  794. return(DATA_ERROR);
  795. }
  796. dz->insams[0] = insams;
  797. break;
  798. case(INPUT_SRATE+4):
  799. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  800. sprintf(errstr,"Cannot read srate sent from TK\n");
  801. return(DATA_ERROR);
  802. }
  803. break;
  804. case(INPUT_CHANNELS+4):
  805. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  806. sprintf(errstr,"Cannot read channels sent from TK\n");
  807. return(DATA_ERROR);
  808. }
  809. break;
  810. case(INPUT_STYPE+4):
  811. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  812. sprintf(errstr,"Cannot read stype sent from TK\n");
  813. return(DATA_ERROR);
  814. }
  815. break;
  816. case(INPUT_ORIGSTYPE+4):
  817. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  818. sprintf(errstr,"Cannot read origstype sent from TK\n");
  819. return(DATA_ERROR);
  820. }
  821. break;
  822. case(INPUT_ORIGRATE+4):
  823. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  824. sprintf(errstr,"Cannot read origrate sent from TK\n");
  825. return(DATA_ERROR);
  826. }
  827. break;
  828. case(INPUT_MLEN+4):
  829. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  830. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  831. return(DATA_ERROR);
  832. }
  833. break;
  834. case(INPUT_DFAC+4):
  835. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  836. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  837. return(DATA_ERROR);
  838. }
  839. break;
  840. case(INPUT_ORIGCHANS+4):
  841. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  842. sprintf(errstr,"Cannot read origchans sent from TK\n");
  843. return(DATA_ERROR);
  844. }
  845. break;
  846. case(INPUT_SPECENVCNT+4):
  847. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  848. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  849. return(DATA_ERROR);
  850. }
  851. dz->specenvcnt = dz->infile->specenvcnt;
  852. break;
  853. case(INPUT_WANTED+4):
  854. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  855. sprintf(errstr,"Cannot read wanted sent from TK\n");
  856. return(DATA_ERROR);
  857. }
  858. break;
  859. case(INPUT_WLENGTH+4):
  860. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  861. sprintf(errstr,"Cannot read wlength sent from TK\n");
  862. return(DATA_ERROR);
  863. }
  864. break;
  865. case(INPUT_OUT_CHANS+4):
  866. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  867. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  868. return(DATA_ERROR);
  869. }
  870. break;
  871. /* RWD these chanegs to samps - tk will have to deal with that! */
  872. case(INPUT_DESCRIPTOR_BYTES+4):
  873. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  874. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  875. return(DATA_ERROR);
  876. }
  877. break;
  878. case(INPUT_IS_TRANSPOS+4):
  879. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  880. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  881. return(DATA_ERROR);
  882. }
  883. break;
  884. case(INPUT_COULD_BE_TRANSPOS+4):
  885. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  886. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  887. return(DATA_ERROR);
  888. }
  889. break;
  890. case(INPUT_COULD_BE_PITCH+4):
  891. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  892. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  893. return(DATA_ERROR);
  894. }
  895. break;
  896. case(INPUT_DIFFERENT_SRATES+4):
  897. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  898. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  899. return(DATA_ERROR);
  900. }
  901. break;
  902. case(INPUT_DUPLICATE_SNDS+4):
  903. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  904. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  905. return(DATA_ERROR);
  906. }
  907. break;
  908. case(INPUT_BRKSIZE+4):
  909. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  910. sprintf(errstr,"Cannot read brksize sent from TK\n");
  911. return(DATA_ERROR);
  912. }
  913. if(inbrksize > 0) {
  914. switch(dz->input_data_type) {
  915. case(WORDLIST_ONLY):
  916. break;
  917. case(PITCH_AND_PITCH):
  918. case(PITCH_AND_TRANSPOS):
  919. case(TRANSPOS_AND_TRANSPOS):
  920. dz->tempsize = inbrksize;
  921. break;
  922. case(BRKFILES_ONLY):
  923. case(UNRANGED_BRKFILE_ONLY):
  924. case(DB_BRKFILES_ONLY):
  925. case(ALL_FILES):
  926. case(ANY_NUMBER_OF_ANY_FILES):
  927. if(dz->extrabrkno < 0) {
  928. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  929. return(DATA_ERROR);
  930. }
  931. if(dz->brksize == NULL) {
  932. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  933. return(PROGRAM_ERROR);
  934. }
  935. dz->brksize[dz->extrabrkno] = inbrksize;
  936. break;
  937. default:
  938. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  939. dz->input_data_type);
  940. return(PROGRAM_ERROR);
  941. }
  942. break;
  943. }
  944. break;
  945. case(INPUT_NUMSIZE+4):
  946. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  947. sprintf(errstr,"Cannot read numsize sent from TK\n");
  948. return(DATA_ERROR);
  949. }
  950. break;
  951. case(INPUT_LINECNT+4):
  952. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  953. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  954. return(DATA_ERROR);
  955. }
  956. break;
  957. case(INPUT_ALL_WORDS+4):
  958. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  959. sprintf(errstr,"Cannot read all_words sent from TK\n");
  960. return(DATA_ERROR);
  961. }
  962. break;
  963. case(INPUT_ARATE+4):
  964. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  965. sprintf(errstr,"Cannot read arate sent from TK\n");
  966. return(DATA_ERROR);
  967. }
  968. break;
  969. case(INPUT_FRAMETIME+4):
  970. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  971. sprintf(errstr,"Cannot read frametime sent from TK\n");
  972. return(DATA_ERROR);
  973. }
  974. dz->frametime = (float)dummy;
  975. break;
  976. case(INPUT_WINDOW_SIZE+4):
  977. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  978. sprintf(errstr,"Cannot read window_size sent from TK\n");
  979. return(DATA_ERROR);
  980. }
  981. break;
  982. case(INPUT_NYQUIST+4):
  983. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  984. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  985. return(DATA_ERROR);
  986. }
  987. break;
  988. case(INPUT_DURATION+4):
  989. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  990. sprintf(errstr,"Cannot read duration sent from TK\n");
  991. return(DATA_ERROR);
  992. }
  993. break;
  994. case(INPUT_MINBRK+4):
  995. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  996. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  997. return(DATA_ERROR);
  998. }
  999. break;
  1000. case(INPUT_MAXBRK+4):
  1001. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  1002. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  1003. return(DATA_ERROR);
  1004. }
  1005. break;
  1006. case(INPUT_MINNUM+4):
  1007. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  1008. sprintf(errstr,"Cannot read minnum sent from TK\n");
  1009. return(DATA_ERROR);
  1010. }
  1011. break;
  1012. case(INPUT_MAXNUM+4):
  1013. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  1014. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  1015. return(DATA_ERROR);
  1016. }
  1017. break;
  1018. default:
  1019. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  1020. return(PROGRAM_ERROR);
  1021. }
  1022. cnt++;
  1023. }
  1024. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  1025. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  1026. return(DATA_ERROR);
  1027. }
  1028. if(true_cnt)
  1029. cnt = true_cnt;
  1030. *cmdlinecnt = 0;
  1031. while(cnt < argc) {
  1032. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  1033. return(exit_status);
  1034. cnt++;
  1035. }
  1036. return(FINISHED);
  1037. }
  1038. /********************************* GET_TK_CMDLINE_WORD *********************************/
  1039. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  1040. {
  1041. if(*cmdlinecnt==0) {
  1042. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  1043. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1044. return(MEMORY_ERROR);
  1045. }
  1046. } else {
  1047. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  1048. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1049. return(MEMORY_ERROR);
  1050. }
  1051. }
  1052. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  1053. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  1054. return(MEMORY_ERROR);
  1055. }
  1056. strcpy((*cmdline)[*cmdlinecnt],q);
  1057. (*cmdlinecnt)++;
  1058. return(FINISHED);
  1059. }
  1060. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  1061. int assign_file_data_storage(int infilecnt,dataptr dz)
  1062. {
  1063. int exit_status;
  1064. int no_sndfile_system_files = FALSE;
  1065. dz->infilecnt = infilecnt;
  1066. if((exit_status = allocate_filespace(dz))<0)
  1067. return(exit_status);
  1068. if(no_sndfile_system_files)
  1069. dz->infilecnt = 0;
  1070. return(FINISHED);
  1071. }
  1072. /************************* SETUP_INTERNAL_ARRAYS_AND_ARRAY_POINTERS *******************/
  1073. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1074. {
  1075. dz->array_cnt = 1;
  1076. dz->larray_cnt = 1;
  1077. if((dz->parray = (double **)malloc(dz->array_cnt * sizeof(double *)))==NULL) {
  1078. sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
  1079. return(MEMORY_ERROR);
  1080. }
  1081. if((dz->lparray = (int **)malloc(dz->larray_cnt * sizeof(int *)))==NULL) {
  1082. sprintf(errstr,"INSUFFICIENT MEMORY for internal long arrays.\n");
  1083. return(MEMORY_ERROR);
  1084. }
  1085. dz->parray[0] = NULL;
  1086. dz->lparray[0] = NULL;
  1087. return(FINISHED);
  1088. }
  1089. /**************************** CHECK_FOFEX_PARAM_VALIDITY_AND_CONSISTENCY *****************************/
  1090. int check_fofex_param_validity_and_consistency(dataptr dz)
  1091. {
  1092. //int n;
  1093. //double time, time2;
  1094. if(dz->brksize[0] == 0) {
  1095. sprintf(errstr,"PITCH PARAMETER MUST BE IN A BREAKPOINT FILE.\n");
  1096. return(DATA_ERROR);
  1097. }
  1098. //n = (dz->brksize[0] - 1) * 2;
  1099. //time = dz->brk[0][n];
  1100. //time2 = (double)dz->insams[0]/(double)dz->infile->srate;
  1101. /* EXTRA SMOOTHING OF PITCH DATA */
  1102. smooth_oct_glitches(dz);
  1103. return FINISHED;
  1104. }
  1105. /********************************************************************************************/
  1106. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1107. {
  1108. if (!strcmp(prog_identifier_from_cmdline,"extract"))
  1109. dz->process = FOFEX_EX;
  1110. else if (!strcmp(prog_identifier_from_cmdline,"construct"))
  1111. dz->process = FOFEX_CO;
  1112. else {
  1113. sprintf(errstr,"Unknown program identification string '%s'\n",
  1114. prog_identifier_from_cmdline);
  1115. return(USAGE_ONLY);
  1116. }
  1117. return(FINISHED);
  1118. }
  1119. /******************************** USAGE1 ********************************/
  1120. int usage1(void)
  1121. {
  1122. fprintf(stderr,
  1123. "\nOPERATIONS USING PITCH-SYNCHRONOUS GRAINS (FOFS) TO (RE)CONSTRUCT SOUNDFILES\n\n"
  1124. "USAGE: fofex NAME (mode) infile outfile parameters: \n"
  1125. "\n"
  1126. "where NAME can be any one of\n"
  1127. "\n"
  1128. "extract construct\n"
  1129. "Type 'fofex extract' for more info on fofex extract..ETC.\n");
  1130. return(USAGE_ONLY);
  1131. }
  1132. /******************************** USAGE2 ********************************/
  1133. int usage2(char *str)
  1134. {
  1135. if(!strcmp(str,"extract")) {
  1136. fprintf(stderr,
  1137. "USAGE:\n"
  1138. "fofex extract 1 infile outfiles 0 pitch-brkpnt-data minlevel fofcnt [-w]\n"
  1139. "OR:\n"
  1140. "fofex extract 1 infile outfiles excludefile pitch-brkpnt-data minlevel fofcnt [-w]\n"
  1141. "OR:\n"
  1142. "fofex extract 2 infile outfile pitch-brkpnt-data time\n"
  1143. "OR:\n"
  1144. "fofex extract 3 infile generic_outfile_name pitch-brkpnt-data minlevel fofcnt [-w]\n"
  1145. "\n"
  1146. "In Mode 1 All FOF(group)s extracted to special FOF-file, to use with 'fofex construct'\n"
  1147. "In Mode 2 A single FOF(group) is extracted\n"
  1148. "In Mode 3 All FOF(group)s are extracted to separate soundfiles\n"
  1149. "\n"
  1150. "PITCH-BRKPNT-DATA a breakpoint file with time and frq information.\n"
  1151. " File may contain zeros (indicating moments of no-signal)\n"
  1152. " but NOT pitch-zeros (indicating moments of no-pitch).\n"
  1153. " It must contain SOME significant frequency information.\n"
  1154. "EXCLUDEFILE Defines areas in source sound from which FOFs will NOT\n"
  1155. " be extracted - info as pairs of times-as-samplecnts.\n"
  1156. "MINLEVEL Level in dBs below the level of loudest FOF found,\n"
  1157. " below which FOFs are rejected.\n"
  1158. " NB Zero means NO FOFS are rejected.\n"
  1159. "FOFCNT Size of FOF group to extract.\n"
  1160. "TIME Time in file at which to extract FOF(group)\n"
  1161. "-w FOFs are windowed (cosine smooth of edges)\n"
  1162. "OUTPUT OF MODE 1 is\n"
  1163. "1) a fofbank sndfile containing extracted FOFS in ascending pitch order\n"
  1164. "2) a fofinfo textfile of position of (semitone) pitchsteps in soundfile\n");
  1165. } else if(!strcmp(str,"construct")) {
  1166. fprintf(stdout,
  1167. "USAGE:\n"
  1168. "fofex construct 1 fofbank outf fofinf pbrk env gain f1\n"
  1169. "fofex construct 2-5 fofbank outf fofinf pbrk env gain [-n]\n"
  1170. "fofex construct 6\n"
  1171. " fofbank outf fofinf pbrk env gain f1 f2 minf maxf [-n]\n"
  1172. "fofex construct 7\n"
  1173. " fofbank outf fofinf pbrk env gain f1 f2 f3 minf maxk minl maxl [-n]\n"
  1174. "\n"
  1175. "MODES: 1 Use 1 FOF only.\n"
  1176. " 2 All FOFs superimposed to make output FOF.\n"
  1177. " 3 Low FOFs superimposed to make output FOF.\n"
  1178. " 4 Midrange FOFs superimposed to make output FOF.\n"
  1179. " 5 High FOFs superimposed to make output FOF.\n"
  1180. " 6 Use 2 FOFs,varying weighting with pitch of output.\n"
  1181. " 7 Use 3 FOFs,vary weighting with pitch & level of output.\n"
  1182. "\n"
  1183. "FOFBANK Soundfile of extracted FOFS created by 'fofex extract'.\n"
  1184. "PBRK Brkpnt file of time/frq info. May contain zeros (no-signal)\n"
  1185. " but NOT pitch-zeros (no-pitch). Must have SOME frq info.\n"
  1186. "ENV Brkpoint-Envelope file, as text.\n"
  1187. "FOFINF A textfile with position of pitchsteps in soundfile,\n"
  1188. " also created by the 'fofex extract' process.\n"
  1189. "GAIN Output gain.\n"
  1190. "F1(2,3) In mode 1, FOF to use, (lowest=1).n"
  1191. " In modes 6,7 use specifically numbered FOFs.\n"
  1192. "MINF MAXF Min and max freqs for variation of internal FOF balance.\n"
  1193. "MINL MAXL Min and max levels(0-1) for variation internal FOF balance.\n"
  1194. "-n Set all FOFs to same level before synthesis.\n"
  1195. "\n");
  1196. } else
  1197. fprintf(stdout,"Unknown option '%s'\n",str);
  1198. return(USAGE_ONLY);
  1199. }
  1200. int usage3(char *str1,char *str2)
  1201. {
  1202. fprintf(stderr,"Insufficient parameters on command line.\n");
  1203. return(USAGE_ONLY);
  1204. }
  1205. /************************* redundant functions: to ensure libs compile OK *******************/
  1206. int assign_process_logic(dataptr dz)
  1207. {
  1208. return(FINISHED);
  1209. }
  1210. void set_legal_infile_structure(dataptr dz)
  1211. {}
  1212. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1213. {
  1214. return(FINISHED);
  1215. }
  1216. int inner_loop
  1217. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1218. {
  1219. return(FINISHED);
  1220. }
  1221. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1222. {
  1223. return(FINISHED);
  1224. }
  1225. /**********************************************************/
  1226. /* UBER-FUNCTION THAT EXTRACTS FOFS, AND CALLS PROCESSES */
  1227. /**********************************************************/
  1228. /************************* FOFEXEX *******************************/
  1229. #define FOFCOSWINDOW (.002)
  1230. int fofexex(dataptr dz)
  1231. {
  1232. int exit_status, OK, real_process;
  1233. /* double maxenv = 10000.0;*/
  1234. int n, m, k, j, a, b, cutcnt, opos, ipos, trofpntcnt = 0;
  1235. int outcnt, fofcnt,exclustt, excluend, maxoutdur=0, minoutdur, temp, inbufstart, inbufend, outbuf_remains;
  1236. int envcnt, minwsize, maxwsize = 0, overflow, bigarray, cutstart = 0, thiscut, lastcut=0;
  1237. int segdur, segstart, segend, newpos;
  1238. int *trofpnt, *cuttime, *outsegs, *outdur, *excludes=NULL;
  1239. double *scanarray, lofrq, hifrq,lopch, hipch, srate = (double)dz->infile->srate;
  1240. float *ibuf, *obuf;
  1241. int *pitchstep=NULL, done, init, range, pcnt=0, got;
  1242. int jj, kk, mm, real_insize;
  1243. int cosedgelen = (int)round(FOFCOSWINDOW * dz->infile->srate);
  1244. int min_fofsamps_for_windowing = (cosedgelen * 2) + 1;
  1245. double *cosedge, val;
  1246. char name_index[200];
  1247. if((cosedge = (double *)malloc(cosedgelen * sizeof(double)))==NULL) {
  1248. sprintf(errstr,"Insufficient memory for FOF windowing.\n");
  1249. return(MEMORY_ERROR);
  1250. }
  1251. for(jj=0,kk=1;jj<cosedgelen;jj++,kk++) {
  1252. val = (double)kk/(double)cosedgelen;
  1253. val = (cos(val * PI) + 1.0)/2.0;
  1254. cosedge[jj] = 1.0 - val;
  1255. }
  1256. if(dz->mode != 1)
  1257. excludes = dz->lparray[0];
  1258. ibuf = dz->sampbuf[0];
  1259. obuf = dz->sampbuf[1];
  1260. if((exit_status = get_min_wsize(&minwsize,0,dz)) < 0)
  1261. return exit_status;
  1262. if(((envcnt = dz->insams[0]/minwsize) * minwsize)!=dz->insams[0])
  1263. envcnt++;
  1264. if((dz->env=(float *)malloc(((envcnt+20) * 2) * sizeof(float)))==NULL) {
  1265. sprintf(errstr,"INSUFFICIENT MEMORY for envelope array.\n");
  1266. return(MEMORY_ERROR);
  1267. }
  1268. bigarray = envcnt+20;
  1269. memset(dz->env,0,(envcnt+20) * 2 * sizeof(float)); /* PRESET env VALS TO ZERO */
  1270. /* PART ENVELOPE vals CAN THEN BE STORED, where env-extract overlaps a buffer boundary */
  1271. fprintf(stdout,"INFO: Extracting pitch-related envelope from file.\n");
  1272. fflush(stdout);
  1273. if((exit_status = extract_pitch_dependent_env_from_sndfile(minwsize,0,&maxwsize,dz))<0)
  1274. return(exit_status);
  1275. envcnt = dz->envend - dz->env;
  1276. // NB EACH ENVELOPE-ITEM CONSISTS OF TWO VALS (time & env-val).
  1277. // REVISED HERE TAKING THIS INTO ACCOUNT
  1278. fprintf(stdout,"INFO: Locating envelope peaks.\n");
  1279. fflush(stdout);
  1280. if((trofpnt = (int *)malloc(envcnt/2 * sizeof(int)))==NULL) {
  1281. sprintf(errstr,"INSUFFICIENT MEMORY TO ANALYSE ENVELOPE.\n");
  1282. return(MEMORY_ERROR);
  1283. }
  1284. if((cuttime = (int *)malloc(bigarray/2 * sizeof(int)))==NULL) {
  1285. sprintf(errstr,"INSUFFICIENT MEMORY TO ANALYSE ENVELOPE.\n");
  1286. return(MEMORY_ERROR);
  1287. }
  1288. if((outsegs = (int *)malloc(bigarray * sizeof(int)))==NULL) {
  1289. sprintf(errstr,"INSUFFICIENT MEMORY TO ANALYSE ENVELOPE.\n");
  1290. return(MEMORY_ERROR);
  1291. }
  1292. if((exit_status = get_envelope_troughs(trofpnt,&trofpntcnt,envcnt,dz))<0)
  1293. return(exit_status);
  1294. if((scanarray = (double *)malloc((maxwsize + 20) * sizeof(double)))==NULL) {
  1295. sprintf(errstr,"Insufficient memory for array to scan for zero-crossings.\n");
  1296. return(MEMORY_ERROR);
  1297. }
  1298. if((sndseekEx(dz->ifd[0],0,0)<0)){
  1299. sprintf(errstr,"sndseek() failed\n");
  1300. return SYSTEM_ERROR;
  1301. }
  1302. dz->total_samps_read = 0;
  1303. if(sloom)
  1304. display_virtual_time(dz->total_samps_read,dz);
  1305. fprintf(stdout,"INFO: Calculating cut points.\n");
  1306. fflush(stdout);
  1307. if((exit_status = read_samps(ibuf,dz))<0)
  1308. return(exit_status);
  1309. k = 0;
  1310. cutcnt = 0;
  1311. if(dz->env[trofpnt[0]] <= 0.0) /* if first trof is at zero, skip that one */
  1312. k++;
  1313. for(n = k;n<trofpntcnt;n++) { /* find places to cut the source */
  1314. if((exit_status = find_min_energy_downward_zero_crossing_point(&n,trofpnt,trofpntcnt,scanarray,&cutcnt,cuttime,cutstart,dz)) < 0)
  1315. return(exit_status);
  1316. if(!dz->zeroset)
  1317. cutcnt++;
  1318. }
  1319. if((exit_status = smooth_cuts(cuttime,&cutcnt,cutstart,dz))<0)
  1320. return(exit_status);
  1321. n = 0;
  1322. m = 0;
  1323. thiscut = 0;
  1324. done = 0;
  1325. outcnt = 0;
  1326. init = 0;
  1327. if(dz->itemcnt > 0) { // REMOVE FOFS IN EXCLUDED AREAS
  1328. while(n < dz->itemcnt) {
  1329. exclustt = excludes[m];
  1330. excluend = excludes[m+1];
  1331. while(cuttime[thiscut] < exclustt) {
  1332. if(init) {
  1333. outsegs[outcnt++] = cuttime[lastcut];
  1334. outsegs[outcnt++] = cuttime[thiscut];
  1335. }
  1336. lastcut = thiscut;
  1337. init = 1;
  1338. if(++thiscut >= cutcnt) {
  1339. done = 1;
  1340. break;
  1341. }
  1342. }
  1343. if(done)
  1344. break;
  1345. while(cuttime[thiscut] < excluend) {
  1346. thiscut++;
  1347. if(thiscut >= cutcnt) {
  1348. done = 1;
  1349. break;
  1350. }
  1351. }
  1352. if(done)
  1353. break;
  1354. lastcut = thiscut;
  1355. if(++thiscut >= cutcnt)
  1356. break;
  1357. n++;
  1358. m += 2;
  1359. }
  1360. }
  1361. while(thiscut < cutcnt) {
  1362. if(init) {
  1363. outsegs[outcnt++] = cuttime[lastcut];
  1364. outsegs[outcnt++] = cuttime[thiscut];
  1365. }
  1366. lastcut = thiscut;
  1367. init = 1;
  1368. thiscut++;
  1369. }
  1370. if((exit_status = remove_zero_signal_areas(outsegs,&outcnt,dz)) < 0)
  1371. return(exit_status);
  1372. if((exit_status = remove_outofrange_fofs(outsegs,&outcnt,dz)) < 0)
  1373. return(exit_status);
  1374. if(dz->param[1] < 0.0) {
  1375. if((exit_status = remove_lolevel_fofs(outsegs,&outcnt,dz)) < 0)
  1376. return(exit_status);
  1377. }
  1378. if(outcnt < 2) {
  1379. sprintf(errstr,"NO VALID FOFS FOUND.\n");
  1380. return(DATA_ERROR);
  1381. }
  1382. fofcnt = outcnt/2;
  1383. if(dz->mode == 1) { // SINGLE FOF AT SPECIFED TIME
  1384. dz->iparam[1] = (int)round(dz->param[1] * srate);
  1385. kk = dz->insams[0] + 4;
  1386. thiscut = -1;
  1387. for(n=0,j=0,k=1;n<fofcnt;n++,j+=2,k+=2) {
  1388. if((temp = abs(dz->iparam[1] - outsegs[j])) < kk) {
  1389. thiscut = n;
  1390. kk = temp;
  1391. } else if((temp = abs(dz->iparam[1] - outsegs[k])) < kk) {
  1392. thiscut = n;
  1393. kk = temp;
  1394. }
  1395. }
  1396. segstart = outsegs[thiscut * 2];
  1397. segend = outsegs[(thiscut * 2) + 1];
  1398. segdur = segend - segstart;
  1399. outcnt = 4;
  1400. newpos = (segstart/F_SECSIZE) * F_SECSIZE;
  1401. if((sndseekEx(dz->ifd[0],newpos,0)<0)) {
  1402. sprintf(errstr,"sndseek() failed\n");
  1403. return SYSTEM_ERROR;
  1404. }
  1405. dz->total_samps_read = newpos;
  1406. if((exit_status = read_samps(ibuf,dz))<0)
  1407. return(exit_status);
  1408. inbufstart = newpos;
  1409. inbufend = newpos + dz->ssampsread;
  1410. ipos = segstart - inbufstart;
  1411. memset((char*)obuf,0,dz->buflen * sizeof(float));
  1412. opos = 0;
  1413. if(segdur > dz->buflen) {
  1414. sprintf(errstr,"FOF too large for buffer.\n");
  1415. return(DATA_ERROR);
  1416. }
  1417. memcpy((char*)obuf,(char*)(ibuf + ipos),segdur * sizeof(float));
  1418. if(!dz->vflag[FOF_UNWIN] && (segdur >= min_fofsamps_for_windowing)) {
  1419. jj = 0;
  1420. kk = segdur - 1;
  1421. for(jj = 0,kk = segdur-1;jj < segdur;jj++,kk--) {
  1422. val = obuf[jj];
  1423. if(jj < cosedgelen)
  1424. val *= cosedge[jj];
  1425. else if (kk < cosedgelen)
  1426. val *= cosedge[kk];
  1427. obuf[jj] = (float)val;
  1428. }
  1429. }
  1430. opos = segdur;
  1431. } else {
  1432. if((outdur = (int *)malloc(fofcnt * sizeof(int)))==NULL) {
  1433. sprintf(errstr,"INSUFFICIENT MEMORY TO TO STORE FOF DURATION INFO.\n");
  1434. return(MEMORY_ERROR);
  1435. }
  1436. if(dz->iparam[2] > 1) {
  1437. a = dz->iparam[2] - 1;
  1438. for(n=0,m=0;n<fofcnt-a;n++,m+=2) { // n COUNTS FOFS, m COUNTS CUTS (at start & end of each)
  1439. OK = 1;
  1440. for(k= 0,mm = m+1,jj = m+2;k < a;k++,mm+=2,jj+=2) { // mm POINTS TO SEGEND, jj TO (NEXT) SEGSTART
  1441. if(outsegs[mm] != outsegs[jj]) { // CHECK FOR N ADJACENT FOFS
  1442. OK = 0;
  1443. break;
  1444. }
  1445. }
  1446. if(OK) // IF FOUND, SET END OF 1ST TO END OF Nth
  1447. outsegs[m+1] = outsegs[m + 1 + (2 * a)];
  1448. else { // ELSE, ELIMINATE THE 1ST FOF OF SET
  1449. kk = m+2; // (IT'S CONTENTS HAVE ALREADY BEEN GRABBED BY PRIOR MULTI-FOFS)
  1450. while(kk < fofcnt * 2) { // BY SHUFFLING FOFS DOWNWARDS, OVERWRITING THE ELIMINATED FOF
  1451. outsegs[kk-2] = outsegs[kk];
  1452. kk++;
  1453. }
  1454. fofcnt--;
  1455. n--;
  1456. m -= 2;
  1457. }
  1458. }
  1459. fofcnt -= a; // LAST N-1 FOFS CANNOT BE GROUPED
  1460. }
  1461. n = 0;
  1462. maxoutdur = 0;
  1463. minoutdur = dz->insams[0];
  1464. for(n=0,j=0,k=1;n<fofcnt;n++,j+=2,k+=2) {
  1465. outdur[n] = outsegs[k] - outsegs[j];
  1466. maxoutdur = max(outdur[n],maxoutdur);
  1467. minoutdur = min(outdur[n],minoutdur);
  1468. }
  1469. if(maxoutdur >= dz->buflen) {
  1470. sprintf(errstr,"LARGEST FOF LONGER THAN BUFFER ???.\n");
  1471. return(PROGRAM_ERROR);
  1472. } else {
  1473. fprintf(stdout,"INFO: FOF separation in output file = %d samples\n",maxoutdur);
  1474. fflush(stdout);
  1475. }
  1476. lofrq = srate/(double)maxoutdur;
  1477. hifrq = srate/(double)minoutdur;
  1478. hztomidi(&lopch,lofrq);
  1479. hztomidi(&hipch,hifrq);
  1480. range = (int)(ceil(hipch - lopch));
  1481. outcnt = (range + 2) * 2; // rounding errors + safety margin : *2 as pitchstep stores 2 vals per item
  1482. // PITCHSTEP will store samp-duration and position (as count of stored FOFs)
  1483. // of FOFs at semitone boundaries in ascending pitch list
  1484. if((pitchstep = (int *)malloc(outcnt * sizeof(int)))==NULL) {
  1485. sprintf(errstr,"Insufficient memory for array to record semitonal pitchstep in FOF data.\n");
  1486. return(MEMORY_ERROR);
  1487. }
  1488. memset((char *)pitchstep,0,outcnt * sizeof(int));
  1489. if((exit_status = create_pitchsteps_semitone_info(lopch,hipch,&pitchstep,&outcnt,srate))<0) {
  1490. sprintf(errstr,"ARRAY SIZE ERROR CREATING PITCH STEPS.\n");
  1491. return(PROGRAM_ERROR);
  1492. }
  1493. n = 0; // SORT FOF SEGS-info INTO DECREASING LENGTH = INCREASING ORIG-PITCH ORDER
  1494. j = 0;
  1495. k = 1;
  1496. while(n<fofcnt-1) {
  1497. m = n;
  1498. m++;
  1499. a = m * 2;
  1500. b = a+1;
  1501. while(m < fofcnt) {
  1502. if(outdur[m] > outdur[n]) {
  1503. temp = outdur[m];
  1504. outdur[m] = outdur[n];
  1505. outdur[n] = temp;
  1506. temp = outsegs[j];
  1507. outsegs[j] = outsegs[a];
  1508. outsegs[a] = temp;
  1509. temp = outsegs[k];
  1510. outsegs[k] = outsegs[b];
  1511. outsegs[b] = temp;
  1512. }
  1513. m++;
  1514. a += 2;
  1515. b += 2;
  1516. }
  1517. n++;
  1518. j += 2;
  1519. k += 2;
  1520. } // store (in outfile) FOFs IN DECREASING LENGTH = INCREASING ORIG-PITCH ORDER
  1521. // at equally spaced intervals, with a length of silence at start to define this interval
  1522. if((sndseekEx(dz->ifd[0],0,0)<0)){
  1523. sprintf(errstr,"sndseek() failed\n");
  1524. return SYSTEM_ERROR;
  1525. }
  1526. dz->total_samps_read = 0;
  1527. if((exit_status = read_samps(ibuf,dz))<0)
  1528. return(exit_status);
  1529. inbufstart = 0;
  1530. inbufend = dz->ssampsread;
  1531. if(dz->mode == 0) {
  1532. memset((char*)obuf,0,dz->buflen * sizeof(float));
  1533. opos = maxoutdur; // SILENCE AT BUF START GIVES MEASURE FOR later FINDING FOF STARTS IN FOFBANK
  1534. outbuf_remains = dz->buflen - opos;
  1535. n = 0;
  1536. j = 0;
  1537. k = 1;
  1538. pcnt = 0;
  1539. got = 0;
  1540. while(n<fofcnt) {
  1541. segdur = outdur[n];
  1542. if(!got) {
  1543. while(segdur < pitchstep[pcnt+1]) { // when FOFs cross a semitone pitch boundary
  1544. pitchstep[pcnt] = n; // store FOF position in FOFbank alongside fof-sampsize (stored previously)
  1545. // Note that we're storing the PREVIOUS FOF which msu have been bigger than pitchstep[pcnt+1]
  1546. // But FOFS are numbered from 1, while fofcnt is running from 0, so "n" stores the previous FOF
  1547. pcnt += 2;
  1548. if(pcnt >= outcnt) {
  1549. got = 1;
  1550. break;
  1551. }
  1552. }
  1553. }
  1554. segstart = outsegs[j];
  1555. segend = outsegs[k];
  1556. if(segstart < inbufstart || segend >= inbufend) {
  1557. newpos = (segstart/F_SECSIZE) * F_SECSIZE;
  1558. if((sndseekEx(dz->ifd[0],newpos,0)<0)){
  1559. sprintf(errstr,"sndseek() failed\n");
  1560. return SYSTEM_ERROR;
  1561. }
  1562. dz->total_samps_read = newpos;
  1563. if((exit_status = read_samps(ibuf,dz))<0)
  1564. return(exit_status);
  1565. inbufstart = newpos;
  1566. inbufend = newpos + dz->ssampsread;
  1567. }
  1568. ipos = segstart - inbufstart;
  1569. if((overflow = -(outbuf_remains - segdur)) > 0) {
  1570. if(!dz->vflag[FOF_UNWIN] && (segdur >= min_fofsamps_for_windowing)) {
  1571. jj = 0;
  1572. kk = segdur - 1;
  1573. for(jj = 0,kk = segdur-1;jj < outbuf_remains;jj++,kk--) {
  1574. val = ibuf[ipos + jj];
  1575. if(jj < cosedgelen)
  1576. val *= cosedge[jj];
  1577. else if (kk < cosedgelen)
  1578. val *= cosedge[kk];
  1579. obuf[opos + jj] = (float)val;
  1580. }
  1581. } else {
  1582. memcpy((char*)(obuf + opos),(char*)(ibuf + ipos),outbuf_remains * sizeof(float));
  1583. }
  1584. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1585. return(exit_status);
  1586. memset((char*)obuf,0,dz->buflen * sizeof(float));
  1587. ipos += outbuf_remains;
  1588. if(dz->vflag[FOF_UNWIN] && (segdur >= min_fofsamps_for_windowing)) {
  1589. mm = 0;
  1590. for(;jj < segdur;jj++,kk--,mm++) {
  1591. val = ibuf[ipos + jj];
  1592. if(jj < cosedgelen)
  1593. val *= cosedge[jj];
  1594. else if (kk < cosedgelen)
  1595. val *= cosedge[kk];
  1596. obuf[mm] = (float)val;
  1597. }
  1598. } else {
  1599. memcpy((char*)obuf,(char*)(ibuf + ipos),overflow * sizeof(float));
  1600. }
  1601. opos += maxoutdur; // FORMANTS ARE EQUALLY SPACED IN OUTFILE
  1602. opos %= dz->buflen;
  1603. } else {
  1604. if(!dz->vflag[FOF_UNWIN] && (segdur >= min_fofsamps_for_windowing)) {
  1605. jj = 0;
  1606. kk = segdur - 1;
  1607. for(jj = 0,kk = segdur-1;jj < segdur;jj++,kk--) {
  1608. val = ibuf[ipos + jj];
  1609. if(jj < cosedgelen)
  1610. val *= cosedge[jj];
  1611. else if (kk < cosedgelen)
  1612. val *= cosedge[kk];
  1613. obuf[opos + jj] = (float)val;
  1614. }
  1615. } else {
  1616. memcpy((char*)(obuf + opos),(char*)(ibuf + ipos),segdur * sizeof(float));
  1617. }
  1618. if((opos += maxoutdur) >= dz->buflen) {
  1619. if((exit_status = write_samps(obuf,dz->buflen,dz))<0)
  1620. return(exit_status);
  1621. memset((char*)obuf,0,dz->buflen * sizeof(float));
  1622. opos %= dz->buflen;
  1623. }
  1624. }
  1625. outbuf_remains = dz->buflen - opos;
  1626. n++;
  1627. j += 2;
  1628. k += 2;
  1629. }
  1630. } else { /* mode == 2 */
  1631. n = 0;
  1632. j = 0;
  1633. k = 1;
  1634. while(n<fofcnt) {
  1635. memset((char*)obuf,0,dz->buflen * sizeof(float));
  1636. segdur = outdur[n];
  1637. segstart = outsegs[j];
  1638. segend = outsegs[k];
  1639. if(segstart < inbufstart || segend >= inbufend) {
  1640. newpos = (segstart/F_SECSIZE) * F_SECSIZE;
  1641. if((sndseekEx(dz->ifd[0],newpos,0)<0)){
  1642. sprintf(errstr,"sndseek() failed\n");
  1643. return SYSTEM_ERROR;
  1644. }
  1645. dz->total_samps_read = newpos;
  1646. if((exit_status = read_samps(ibuf,dz))<0)
  1647. return(exit_status);
  1648. inbufstart = newpos;
  1649. inbufend = newpos + dz->ssampsread;
  1650. }
  1651. ipos = segstart - inbufstart;
  1652. segend = ipos + segdur;
  1653. if(segend > dz->buflen) {
  1654. sprintf(errstr,"FOF too long for output buffer.\n");
  1655. return(DATA_ERROR);
  1656. }
  1657. memcpy((char*)obuf,(char*)(ibuf + ipos),segdur * sizeof(float));
  1658. if(dz->vflag[FOF_UNWIN] && (segdur >= min_fofsamps_for_windowing)) {
  1659. for(jj = 0,kk = segdur - 1;jj < segdur;jj++,kk--) {
  1660. val = obuf[jj];
  1661. if(jj < cosedgelen)
  1662. val *= cosedge[jj];
  1663. else if (kk < cosedgelen)
  1664. val *= cosedge[kk];
  1665. obuf[jj] = (float)val;
  1666. }
  1667. }
  1668. strcpy(dz->outfilename,dz->wordstor[0]);
  1669. sprintf(name_index,"%d",n);
  1670. strcat(dz->outfilename,name_index);
  1671. real_insize = dz->insams[0];
  1672. real_process = dz->process_type;
  1673. dz->insams[0] = segdur;
  1674. dz->process_type = EQUAL_SNDFILE;
  1675. if((exit_status = create_sized_outfile(dz->outfilename,dz))<0) {
  1676. fprintf(stdout, "WARNING: Soundfile %s already exists.\n", dz->outfilename);
  1677. fflush(stdout);
  1678. dz->process_type = real_process;
  1679. dz->insams[0] = real_insize;
  1680. dz->ofd = -1;
  1681. return(FINISHED);
  1682. }
  1683. if((exit_status = write_samps(obuf,segdur,dz))<0)
  1684. return exit_status;
  1685. dz->outfiletype = SNDFILE_OUT; /* allows header to be written */
  1686. if((exit_status = headwrite(dz->ofd,dz))<0)
  1687. return(exit_status);
  1688. dz->process_type = real_process; /* restore true status */
  1689. dz->outfiletype = NO_OUTPUTFILE; /* restore true status */
  1690. dz->insams[0] = real_insize; /* restore true insize */
  1691. if((exit_status = reset_peak_finder(dz))<0)
  1692. return(exit_status);
  1693. if(sndcloseEx(dz->ofd) < 0) {
  1694. fprintf(stdout,"WARNING: Can't close output soundfile %s\n",dz->outfilename);
  1695. fflush(stdout);
  1696. }
  1697. dz->ofd = -1;
  1698. n++;
  1699. j += 2;
  1700. k += 2;
  1701. }
  1702. return(FINISHED);
  1703. }
  1704. }
  1705. if(opos > 0) {
  1706. if((exit_status = write_samps(obuf,opos,dz))<0)
  1707. return(exit_status);
  1708. }
  1709. if(dz->mode == 0) {
  1710. outcnt = pcnt;
  1711. n = 0;
  1712. while(n < outcnt) {
  1713. fprintf(dz->fp,"%d %d\n",pitchstep[n],pitchstep[n+1]);
  1714. n += 2;
  1715. }
  1716. fclose(dz->fp);
  1717. dz->itemcnt = maxoutdur; /* Used to set FOFbank header property */
  1718. }
  1719. return FINISHED;
  1720. }
  1721. /************************* FOFEXCO *******************************/
  1722. int fofexco(dataptr dz)
  1723. {
  1724. int exit_status;
  1725. int k, klim=0, outpos, ipos, obufstart, writend;
  1726. int *fofindex = dz->lparray[0];
  1727. float *ibuf, *obuf1, *obuf2, *fofbuf=NULL, maxval = 0.0f;
  1728. int done;
  1729. double outdur, srate, mintimestep, time, *norm=NULL;
  1730. int minsamplen, unitlen;
  1731. int totalfofs;
  1732. double *sumfofs=NULL, max_samp, maxpch, minpch, thispch, prange=0.0, temp;
  1733. double hilevel=0.0, lolevel=0.0, levelrange=0.0, thislevel, gainhi, gainlo, gain2hi, gain2lo, fofval;
  1734. int n, fofbuflen, fofpos1, fofpos2, fofpos3;
  1735. char tempstr[200];
  1736. int splicelen = (int)round(0.005 * dz->infile->srate);
  1737. double splicincr = 1.0/(double)splicelen, splicelevel = 1.0 - splicincr;
  1738. srate = (double)dz->infile->srate;
  1739. ibuf = dz->sampbuf[0];
  1740. if((exit_status = read_samps(ibuf,dz))<0)
  1741. return(exit_status);
  1742. //inbufstart = 0;
  1743. //inbufend = dz->ssampsread;
  1744. unitlen = dz->descriptor_samps; // SEGMENT LENGTH FOR FOF-STORAGE READ FROM HEADER
  1745. totalfofs = dz->insams[0]/unitlen; // TOTAL NUMBER OF STORED FOFS + ZEROED MEASURING UNIT AT START
  1746. totalfofs--; // TOTAL NUMBER OF STORED FOFS
  1747. if(dz->mode == FOF_MEASURE) {
  1748. sprintf(tempstr,"%d %d\n",unitlen,totalfofs);
  1749. if(fputs(tempstr,dz->fp)<0) {
  1750. sprintf(errstr,"Failed to write FOFcount info to textfile.\n");
  1751. return(SYSTEM_ERROR);
  1752. }
  1753. return FINISHED;
  1754. }
  1755. outdur = dz->brk[0][(dz->brksize[0] * 2) - 2]; // Final time in pitchdata input
  1756. obuf1 = dz->sampbuf[1];
  1757. obuf2 = dz->sampbuf[2];
  1758. memset((char *)obuf1,0,dz->buflen * sizeof(float));
  1759. memset((char *)obuf2,0,dz->buflen * sizeof(float));
  1760. //maxsamplen = fofindex[1];
  1761. minsamplen = fofindex[(dz->itemcnt * 2) - 1];
  1762. mintimestep = (double)minsamplen/srate;
  1763. mintimestep /= 4.0; // WHEN WE HIT SILENCE IN PITCHFILE, CREEP ALONG PITCHDATA WITH THIS MINSTEP
  1764. // TILL WE GET TO NEXT REAL VAL
  1765. obufstart = 0;
  1766. //obufend = dz->buflen;
  1767. if(dz->mode == FOF_LOHI) {
  1768. if((dz->iparam[3] > totalfofs) || (dz->iparam[4] > totalfofs)) {
  1769. sprintf(errstr,"There are only %d FOFs. FOF number(s) out of range.\n",totalfofs);
  1770. return(DATA_ERROR);
  1771. }
  1772. // GET PITCHRANGE OVER WHICH BALANCE BETWEEN CHOSEN FOFS WILL VARY
  1773. hztomidi(&minpch,dz->param[5]);
  1774. hztomidi(&maxpch,dz->param[6]);
  1775. if(maxpch < minpch) {
  1776. temp = minpch;
  1777. minpch = maxpch;
  1778. maxpch = temp;
  1779. }
  1780. prange = maxpch - minpch;
  1781. } else if(dz->mode == FOF_TRIPLE) {
  1782. if((dz->iparam[3] > totalfofs) || (dz->iparam[4] > totalfofs) || (dz->iparam[5] > totalfofs)) {
  1783. sprintf(errstr,"There are only %d FOFs. FOF number(s) out of range.\n",totalfofs);
  1784. return(DATA_ERROR);
  1785. }
  1786. // GET PITCHRANGE OVER WHICH BALANCE BETWEEN CHOSEN FOFS WILL VARY
  1787. hztomidi(&minpch,dz->param[6]);
  1788. hztomidi(&maxpch,dz->param[7]);
  1789. if(maxpch < minpch) {
  1790. temp = minpch;
  1791. minpch = maxpch;
  1792. maxpch = temp;
  1793. }
  1794. prange = maxpch - minpch;
  1795. // GET (LEVELRANGE OVER WHICH BALANCE BETWEEN CHOSEN FOFS WILL VARY
  1796. lolevel = dz->param[8];
  1797. hilevel = dz->param[9];
  1798. if(hilevel < lolevel) {
  1799. temp = lolevel;
  1800. lolevel = hilevel;
  1801. hilevel = lolevel;
  1802. }
  1803. levelrange = hilevel - lolevel;
  1804. }
  1805. if(dz->mode == FOF_LOHI || dz->mode == FOF_TRIPLE) { // CREATE STORE FOR 2 OR 3 FOFS USED IN CONSTRUCTION
  1806. fofbuflen = unitlen * 3 * sizeof(float);
  1807. if((fofbuf = (float *)malloc(fofbuflen))==NULL) {
  1808. sprintf(errstr,"Insufficient memory to store echoes.\n");
  1809. return(MEMORY_ERROR);
  1810. }
  1811. ipos = dz->iparam[3] * unitlen;
  1812. klim = ipos + unitlen;
  1813. if(ipos + unitlen > dz->ssampsread) {
  1814. if((sndseekEx(dz->ifd[0],ipos,0)<0)){
  1815. sprintf(errstr,"sndseek() failed\n");
  1816. return SYSTEM_ERROR;
  1817. }
  1818. dz->total_samps_read = ipos;
  1819. if((exit_status = read_samps(ibuf,dz))<0)
  1820. return(exit_status);
  1821. ipos = ipos - (dz->total_samps_read - dz->ssampsread);
  1822. }
  1823. for(k=0;k<unitlen;k++)
  1824. fofbuf[k] = ibuf[ipos++];
  1825. ipos = dz->iparam[4] * unitlen;
  1826. if((sndseekEx(dz->ifd[0],ipos,0)<0)){
  1827. sprintf(errstr,"sndseek() failed\n");
  1828. return SYSTEM_ERROR;
  1829. }
  1830. dz->total_samps_read = ipos;
  1831. if((exit_status = read_samps(ibuf,dz))<0)
  1832. return(exit_status);
  1833. ipos = ipos - (dz->total_samps_read - dz->ssampsread);
  1834. n = unitlen;
  1835. for(k=0;k<unitlen;k++)
  1836. fofbuf[n++] = ibuf[ipos++];
  1837. if(dz->mode == FOF_TRIPLE) {
  1838. ipos = dz->iparam[5] * unitlen;
  1839. if((sndseekEx(dz->ifd[0],ipos,0)<0)){
  1840. sprintf(errstr,"sndseek() failed\n");
  1841. return SYSTEM_ERROR;
  1842. }
  1843. dz->total_samps_read = ipos;
  1844. if((exit_status = read_samps(ibuf,dz))<0)
  1845. return(exit_status);
  1846. ipos = ipos - (dz->total_samps_read - dz->ssampsread);
  1847. n = unitlen * 2;
  1848. for(k=0;k<unitlen;k++)
  1849. fofbuf[n++] = ibuf[ipos++];
  1850. }
  1851. if((sndseekEx(dz->ifd[0],0,0)<0)){
  1852. sprintf(errstr,"sndseek() failed\n");
  1853. return SYSTEM_ERROR;
  1854. }
  1855. if((exit_status = read_samps(ibuf,dz))<0)
  1856. return(exit_status);
  1857. } // CALCULATE NORMALISATION COEEFICIENTS
  1858. if(dz->mode != FOF_SINGLE) {
  1859. if(dz->vflag[FOF_NORM]) {
  1860. establish_normalisers(unitlen,dz);
  1861. norm = dz->parray[0];
  1862. }
  1863. if((sndseekEx(dz->ifd[0],0,0)<0)){
  1864. sprintf(errstr,"sndseek() failed\n");
  1865. return SYSTEM_ERROR;
  1866. }
  1867. dz->total_samps_read = 0;
  1868. if((exit_status = read_samps(ibuf,dz))<0)
  1869. return(exit_status);
  1870. }
  1871. if(dz->mode <= FOF_HISUM) { // USE A SINGLE FOF, OR SUM ALL, OR A RANGE OF, FOFS
  1872. if((sumfofs = (double *)malloc(unitlen * sizeof(double)))==NULL) {
  1873. sprintf(errstr,"Insufficient memory to sum FOFs.\n");
  1874. return(MEMORY_ERROR);
  1875. }
  1876. memset((char *)sumfofs,0,unitlen * sizeof(double));
  1877. k = 1;
  1878. switch(dz->mode) {
  1879. case(FOF_SINGLE):
  1880. k = dz->iparam[3];
  1881. if(k > totalfofs)
  1882. k = totalfofs;
  1883. klim = k;
  1884. break;
  1885. case(FOF_SUM):
  1886. k = 1;
  1887. klim = totalfofs;
  1888. break;
  1889. case(FOF_LOSUM):
  1890. k = 1;
  1891. klim = totalfofs/3;
  1892. break;
  1893. case(FOF_MIDSUM):
  1894. k = totalfofs/3;
  1895. klim = (2 * totalfofs)/3;
  1896. break;
  1897. case(FOF_HISUM):
  1898. k = (2 * totalfofs)/3;
  1899. klim = totalfofs;
  1900. break;
  1901. }
  1902. ipos = (k * unitlen);
  1903. while(ipos >= dz->ssampsread) {
  1904. if((exit_status = read_samps(ibuf,dz))<0)
  1905. return(exit_status);
  1906. ipos -= dz->buflen;
  1907. }
  1908. while(k <= klim) {
  1909. n = 0;
  1910. while(n < unitlen) {
  1911. if((dz->mode != FOF_SINGLE) && dz->vflag[FOF_NORM])
  1912. sumfofs[n] += (ibuf[ipos] * norm[k]);
  1913. else
  1914. sumfofs[n] += ibuf[ipos];
  1915. ipos++;
  1916. if(ipos >= dz->ssampsread) {
  1917. if((exit_status = read_samps(ibuf,dz))<0)
  1918. return(exit_status);
  1919. ipos = 0;
  1920. }
  1921. n++;
  1922. }
  1923. k++;
  1924. }
  1925. max_samp = 0.0;
  1926. n = 0;
  1927. while(n < unitlen) {
  1928. max_samp = max(max_samp,fabs(sumfofs[n]));
  1929. n++;
  1930. }
  1931. n = 0;
  1932. while(n < unitlen) {
  1933. sumfofs[n] = (sumfofs[n]/max_samp) * FOF_NORM_LEVEL;
  1934. n++;
  1935. }
  1936. if((sndseekEx(dz->ifd[0],0,0)<0)){
  1937. sprintf(errstr,"sndseek() failed\n");
  1938. return SYSTEM_ERROR;
  1939. }
  1940. dz->total_samps_read = 0;
  1941. if((exit_status = read_samps(ibuf,dz))<0)
  1942. return(exit_status);
  1943. }
  1944. time = 0.0;
  1945. done = 0;
  1946. writend = 0;
  1947. // GENERATE APPROPRIATE FOFS AT REQUIRED PITCH
  1948. while(time <= outdur) {
  1949. if((exit_status = read_values_from_all_existing_brktables(time,dz))<0) {
  1950. sprintf(errstr,"FAILED TO READ PITCH DATA\n");
  1951. return(DATA_ERROR);
  1952. }
  1953. while(dz->param[0] < 0) { // If hit no-pitch pitchfile, creep along data till we find some real pitch
  1954. time += mintimestep;
  1955. if(time >= outdur) {
  1956. done = 1;
  1957. break;
  1958. }
  1959. if((exit_status = read_values_from_all_existing_brktables(time,dz))<0) {
  1960. sprintf(errstr,"FAILED TO READ PITCH DATA\n");
  1961. return(DATA_ERROR);
  1962. }
  1963. }
  1964. if(done)
  1965. break;
  1966. outpos = (int)round(time * srate); // Position it at appropriate place in output.
  1967. outpos -= obufstart;
  1968. while(outpos >= dz->buflen) { // There might be silence to write, so "while"
  1969. n = 0;
  1970. while(n < dz->buflen)
  1971. maxval = (float)max(maxval,fabs(obuf1[n++]));
  1972. if((exit_status = write_samps(obuf1,dz->buflen,dz))<0)
  1973. return(exit_status);
  1974. memcpy((char *)obuf1,(char *)obuf2,dz->buflen * sizeof(float));
  1975. memset((char *)obuf2,0,dz->buflen * sizeof(float));
  1976. outpos -= dz->buflen;
  1977. obufstart += dz->buflen;
  1978. }
  1979. switch(dz->mode) {
  1980. case(FOF_SINGLE):
  1981. case(FOF_SUM):
  1982. case(FOF_LOSUM):
  1983. case(FOF_MIDSUM):
  1984. case(FOF_HISUM):
  1985. for(k=0;k<unitlen;k++) {
  1986. obuf1[outpos] = (float)(obuf1[outpos] + (sumfofs[k] * dz->param[1] * dz->param[2]));
  1987. outpos++;
  1988. }
  1989. break;
  1990. case(FOF_LOHI):
  1991. hztomidi(&thispch,(double)srate/(double)dz->param[0]);
  1992. thispch = max(thispch,minpch);
  1993. thispch = min(thispch,maxpch);
  1994. gainhi = ((thispch - minpch)/prange) * 0.75;
  1995. gainlo = 1.0 - gainhi;
  1996. fofpos1 = 0;
  1997. fofpos2 = unitlen;
  1998. for(k=0;k<unitlen;k++) {
  1999. if(dz->vflag[FOF_NORM]) {
  2000. fofval = (fofbuf[fofpos1] * norm[dz->iparam[3]] * gainlo) + (fofbuf[fofpos2] * norm[dz->iparam[4]] * gainhi);
  2001. } else {
  2002. fofval = (fofbuf[fofpos1] * gainlo) + (fofbuf[fofpos2] * gainhi);
  2003. }
  2004. obuf1[outpos] = (float)(obuf1[outpos] + (fofval * dz->param[1] * dz->param[2]));
  2005. outpos++;
  2006. fofpos1++;
  2007. fofpos2++;
  2008. }
  2009. break;
  2010. case(FOF_TRIPLE):
  2011. hztomidi(&thispch,(double)srate/(double)dz->param[0]);
  2012. thispch = max(thispch,minpch);
  2013. thispch = min(thispch,maxpch);
  2014. gainhi = ((thispch - minpch)/prange) * 0.75; // TESSITURA MAKES THIS MUCH DIFERENCE
  2015. gainlo = 1.0 - gainhi;
  2016. thislevel = dz->param[1];
  2017. thislevel = max(thispch,lolevel);
  2018. thislevel = min(thispch,hilevel);
  2019. gain2hi = ((thislevel - lolevel)/levelrange) * 0.33; // LOUDNESS MAKES THIS MUCH DIFF
  2020. gain2lo = 1.0 - gain2hi;
  2021. fofpos1 = 0;
  2022. fofpos2 = unitlen;
  2023. fofpos3 = unitlen * 2;
  2024. for(k=0;k<unitlen;k++) {
  2025. if(dz->vflag[FOF_NORM]) {
  2026. fofval = (fofbuf[fofpos1] * norm[dz->iparam[3]] * gainlo) + (fofbuf[fofpos2] * norm[dz->iparam[4]] * gainhi);
  2027. fofval = (fofval *gain2lo) + (fofbuf[fofpos3] * norm[dz->iparam[5]] * gain2hi);
  2028. } else {
  2029. fofval = (fofbuf[fofpos1] * gainlo) + (fofbuf[fofpos2] * gainhi);
  2030. fofval = (fofval *gain2lo) + (fofbuf[fofpos3] * gain2hi);
  2031. }
  2032. obuf1[outpos] = (float)(obuf1[outpos] + (fofval * dz->param[1] * dz->param[2]));
  2033. outpos++;
  2034. fofpos1++;
  2035. fofpos2++;
  2036. fofpos3++;
  2037. }
  2038. break;
  2039. }
  2040. writend = max(outpos,writend);
  2041. time += 1.0/dz->param[0]; /* Advance time by wavelength of last FOF used */
  2042. }
  2043. if(writend > 0) {
  2044. n = writend - 1;
  2045. while(n > 0) { /* Ignore silence at end of 'writend' = silent end of FOF-element */
  2046. if(obuf1[n] == 0.0f)
  2047. n--;
  2048. else {
  2049. n++;
  2050. break;
  2051. }
  2052. }
  2053. writend = n;
  2054. n = 0;
  2055. while(n < writend)
  2056. maxval = (float)max(maxval,fabs(obuf1[n++]));
  2057. if(writend > splicelen) { /* splice end if room to do so */
  2058. n = writend - splicelen;
  2059. while(n < writend) {
  2060. obuf1[n] = (float)(obuf1[n] * splicelevel);
  2061. splicelevel -= splicincr;
  2062. if(splicelevel < 0.0)
  2063. splicelevel = 0.0;
  2064. n++;
  2065. }
  2066. }
  2067. if((exit_status = write_samps(obuf1,writend,dz))<0)
  2068. return(exit_status);
  2069. }
  2070. fprintf(stdout,"INFO: MAXSAMP %f\n",maxval);
  2071. fflush(stdout);
  2072. return FINISHED;
  2073. }
  2074. /************************* EXTRACT_PITCH_DEPENDENT_ENV_FROM_SNDFILE *******************************/
  2075. int extract_pitch_dependent_env_from_sndfile(int minwsize,int k,int *maxwsize,dataptr dz)
  2076. {
  2077. int exit_status;
  2078. double tconvertor = 1.0/(double)dz->infile->srate;
  2079. double fconvertor = (double)dz->infile->srate/WINDIV;
  2080. int start_samp = 0, envwindow_sampsize, big_envwindow_sampsize, here = 0, start_buf = 0;
  2081. float *env = dz->env;
  2082. double time = 0.0;
  2083. if((dz->ssampsread = fgetfbufEx(dz->sampbuf[0], dz->buflen,dz->ifd[k],0)) < 0) {
  2084. sprintf(errstr,"Can't read samples from input soundfile %d\n",k+1);
  2085. return(SYSTEM_ERROR);
  2086. }
  2087. if(dz->ssampsread < dz->insams[k]) {
  2088. if((dz->ssampsread = fgetfbufEx(dz->sampbuf[1], dz->buflen,dz->ifd[k],0)) < 0) {
  2089. sprintf(errstr,"Can't read samples from input soundfile %d\n",k+1);
  2090. return(SYSTEM_ERROR);
  2091. }
  2092. }
  2093. if((exit_status = read_value_from_brktable(time,k,dz))<0)
  2094. return(exit_status);
  2095. if(dz->param[k] < 0.0) /* no-pitch */
  2096. envwindow_sampsize = minwsize;
  2097. else
  2098. envwindow_sampsize = (int)round(fconvertor/dz->param[k]);
  2099. while(here < dz->insams[k]) {
  2100. if(here - start_buf >= dz->buflen) {
  2101. memset((char *)dz->sampbuf[0],0,dz->buflen * sizeof(float));
  2102. memcpy((char *)dz->sampbuf[0],(char *)dz->sampbuf[1],dz->buflen * sizeof(float));
  2103. start_buf += dz->buflen;
  2104. if(dz->total_samps_read < dz->insams[k]) {
  2105. if((dz->ssampsread = fgetfbufEx(dz->sampbuf[1], dz->buflen,dz->ifd[k],0)) < 0) {
  2106. sprintf(errstr,"Can't read samples from input soundfile %d\n",k+1);
  2107. return(SYSTEM_ERROR);
  2108. }
  2109. }
  2110. }
  2111. big_envwindow_sampsize = envwindow_sampsize * 2;
  2112. *env++ = (float)time;
  2113. if(here + big_envwindow_sampsize >= dz->insams[k]) {
  2114. here -= envwindow_sampsize;
  2115. big_envwindow_sampsize = dz->insams[k] - here;
  2116. *env++ = getmaxsampr(start_samp,big_envwindow_sampsize,dz->sampbuf[0]);
  2117. break;
  2118. }
  2119. start_samp = here - start_buf;
  2120. *env++ = getmaxsampr(start_samp,big_envwindow_sampsize,dz->sampbuf[0]);
  2121. here += envwindow_sampsize;
  2122. time = (float)(here * tconvertor);
  2123. if((exit_status = read_value_from_brktable(time,k,dz))<0)
  2124. return(exit_status);
  2125. if(dz->param[k] < 0.0) /* no-pitch */
  2126. envwindow_sampsize = minwsize;
  2127. else
  2128. envwindow_sampsize = (int)round(fconvertor/dz->param[k]);
  2129. if(envwindow_sampsize > *maxwsize)
  2130. *maxwsize = envwindow_sampsize;
  2131. }
  2132. *maxwsize *= 2; /* using overlapping windows */
  2133. dz->envend = env;
  2134. memset((char *)dz->sampbuf[0],0,dz->buflen * sizeof(float));
  2135. memset((char *)dz->sampbuf[1],0,dz->buflen * sizeof(float));
  2136. return FINISHED;
  2137. }
  2138. /*************************** GETMAXSAMPR ******************************/
  2139. float getmaxsampr(int startsamp, int sampcnt,float *buffer)
  2140. {
  2141. int i, endsamp = startsamp + sampcnt;
  2142. float thisval, thismaxsamp = -1;
  2143. for(i = startsamp; i<endsamp; i++) {
  2144. if((thisval = (float)fabs(buffer[i]))>thismaxsamp)
  2145. thismaxsamp = thisval;
  2146. }
  2147. return(thismaxsamp);
  2148. }
  2149. /************************** GET_MIN_WSIZE **************************/
  2150. int get_min_wsize(int *minwsize, int k, dataptr dz) {
  2151. int n,m;
  2152. int wsize;
  2153. double fconvertor = (double)dz->infile->srate/WINDIV, frq;
  2154. *minwsize = dz->insams[k];
  2155. for(n=0,m=1;n<dz->brksize[k];n++,m+=2) {
  2156. frq = dz->brk[k][m];
  2157. if(frq > 0.0) {
  2158. wsize = (int)round(fconvertor/frq);
  2159. if(wsize < *minwsize)
  2160. *minwsize = wsize;
  2161. }
  2162. }
  2163. if(*minwsize >= dz->insams[k])
  2164. return(DATA_ERROR);
  2165. return FINISHED;
  2166. }
  2167. /************************** FIND_MIN_ENERGY_DOWNWARD_ZERO_CROSSING_POINT **************************/
  2168. int find_min_energy_downward_zero_crossing_point(int *n,int *trofpnt,int trofpntcnt,
  2169. double *scanarray,int *cutcnt,int *cut,int cutstart,dataptr dz)
  2170. {
  2171. int exit_status;
  2172. int check;
  2173. float starttime, val, *buf = dz->sampbuf[0];
  2174. int wsize, thissamp, hisamp, losamp, j, zc_cnt, at;
  2175. int endsamp, startsamp, seglen;
  2176. int newpos, diff, losampinbuf, hisampinbuf, here, there, localpeakcnt;
  2177. int k, first_downcross, mindiff, goalseglen, newseglen, thiscut;
  2178. double official_pitchlen;
  2179. int pitchseg_lolimit, pitchseg_hilimit;
  2180. int done;
  2181. int pitchwindow, ideal_place, last_startsamp, thiscutinbuf, lastcut, lastcutinbuf;
  2182. int seg1, seg2;
  2183. double rat;
  2184. endsamp = dz->total_samps_read;
  2185. startsamp = endsamp - dz->ssampsread;
  2186. j = trofpnt[*n];
  2187. starttime = dz->env[j];
  2188. wsize = read_validpitch_wsize_in_samps_from_brktable(starttime,0,dz);
  2189. thissamp = (int)round(starttime * (double)dz->infile->srate);
  2190. losamp = thissamp;
  2191. if((exit_status = read_value_from_brktable(starttime,0,dz))<0) /* get pitch at start of window */
  2192. return(exit_status);
  2193. if(losamp >= dz->insams[0])
  2194. return(FINISHED);
  2195. if(losamp >= endsamp || losamp < startsamp) {
  2196. newpos = (losamp/F_SECSIZE) * F_SECSIZE;
  2197. if((sndseekEx(dz->ifd[0],newpos,0)<0)){
  2198. sprintf(errstr,"sndseek() failed\n");
  2199. return SYSTEM_ERROR;
  2200. }
  2201. dz->total_samps_read = newpos;
  2202. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  2203. return(exit_status);
  2204. endsamp = dz->total_samps_read;
  2205. startsamp = endsamp - dz->ssampsread;
  2206. }
  2207. hisamp = min(dz->insams[0],thissamp + wsize); /* get end-of-search area from wtime & half-wsize */
  2208. if(hisamp >= dz->insams[0])
  2209. hisamp = dz->insams[0];
  2210. if(hisamp > endsamp) {
  2211. newpos = (losamp/F_SECSIZE) * F_SECSIZE; /* if end-of--search beyond end of current buf */
  2212. /* adjust buffer to contain whole search area */
  2213. if((sndseekEx(dz->ifd[0],newpos,0)<0)){
  2214. sprintf(errstr,"sndseek() failed\n");
  2215. return SYSTEM_ERROR;
  2216. }
  2217. dz->total_samps_read = newpos;
  2218. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  2219. return(exit_status);
  2220. endsamp = dz->total_samps_read;
  2221. startsamp = endsamp - dz->ssampsread;
  2222. }
  2223. losampinbuf = losamp - startsamp; /* get search ends relative to buffer */
  2224. hisampinbuf = hisamp - startsamp;
  2225. if(dz->param[0] > 0) {
  2226. pitchwindow = (int)round((double)dz->infile->srate/dz->param[0]);
  2227. ideal_place = cut[(*cutcnt) - 1] + pitchwindow;
  2228. ideal_place -= startsamp;
  2229. } else {
  2230. ideal_place = -1;
  2231. }
  2232. here = losampinbuf;
  2233. there = hisampinbuf;
  2234. zc_cnt = count_zerocrossings(losampinbuf,hisampinbuf,buf);
  2235. while(zc_cnt > 5) /* Divide segment into 4 quarters, making 3 overlapping areas, while any area has >= 5 zcrossings */
  2236. zc_cnt = triangulate_env(&here,&there,ideal_place,buf); /* and find area with least energy */
  2237. losamp = here + startsamp;
  2238. dz->zeroset = 0;
  2239. if((exit_status = find_the_local_peaks(&here,&there,buf,n,trofpntcnt,trofpnt,
  2240. &startsamp,&endsamp,losamp,cut,*cutcnt,scanarray,scanarray,&localpeakcnt,&first_downcross,dz) )<0)
  2241. return(exit_status);
  2242. if(exit_status == FINISHED)
  2243. dz->zeroset = 1;
  2244. if(dz->zeroset)
  2245. return(FINISHED);
  2246. if((exit_status = mark_cut(cutcnt,cut,localpeakcnt,scanarray,here,there,startsamp,first_downcross,starttime,1,dz))<0)
  2247. return(exit_status);
  2248. if((*cutcnt)-1 < cutstart) /* FIND LENGTH OF SEGMENT GENERATED */
  2249. seglen = cut[*cutcnt];
  2250. else
  2251. seglen = cut[*cutcnt] - cut[(*cutcnt)-1];
  2252. if(seglen == 0) { /* ELIMINATE ZERO-LENGTH SEGMENTS (CUTS AT SAME TIME) */
  2253. (*cutcnt)--;
  2254. } else if(*cutcnt > cutstart && dz->param[0] > 0) {
  2255. /* CHECK THE LENGTH OF THE WINDOW AGAINST WHAT WE'D PREDICT FROM THE PITCH VALUE */
  2256. check = 1;
  2257. while(check) {
  2258. official_pitchlen = (double)dz->infile->srate/dz->param[0];
  2259. pitchseg_lolimit = (int)round(official_pitchlen/PITCHERROR);
  2260. pitchseg_hilimit = (int)round(official_pitchlen * PITCHERROR);
  2261. /* IF SEGLEN IS ACCEPTABLE, BREAK */
  2262. if(seglen > pitchseg_lolimit && seglen < pitchseg_hilimit) {
  2263. break;
  2264. }
  2265. if(seglen < pitchseg_lolimit) { /* TOO SHORT ITEM, DELETE FROM CUTLIST */
  2266. (*cutcnt)--;
  2267. break;
  2268. }
  2269. /* TOO LONG ITEM */
  2270. /* BRUTE FORCE METHOD, CUT AT ANY DOWN ZEROCROSS NEAR THE RIGHT TIME */
  2271. /* TRY TO MAKE A CUT HALF-WAY THROUGH THE SEGMENT */
  2272. at = 0;
  2273. mindiff = seglen;
  2274. goalseglen = seglen/2; /* set the goal segement length to half the current seglen */
  2275. /* Geteach zero-crossing in this segment */
  2276. last_startsamp = -1;
  2277. thiscutinbuf = cut[*cutcnt] - startsamp;
  2278. lastcut = cut[(*cutcnt) - 1];
  2279. lastcutinbuf = lastcut - startsamp;
  2280. if(lastcutinbuf < 0) {
  2281. last_startsamp = startsamp;
  2282. if((sndseekEx(dz->ifd[0],lastcut,0)<0)){
  2283. sprintf(errstr,"sndseek() failed\n");
  2284. return SYSTEM_ERROR;
  2285. }
  2286. dz->total_samps_read = lastcut;
  2287. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  2288. return(exit_status);
  2289. startsamp = dz->total_samps_read - dz->ssampsread;
  2290. thiscutinbuf -= lastcutinbuf; /* lastcutinbuf is -ve */
  2291. lastcutinbuf = 0;
  2292. }
  2293. done = 0;
  2294. k = lastcutinbuf;
  2295. val = buf[++k];
  2296. while(k < thiscutinbuf) {
  2297. if(val > 0.0) {
  2298. while(val >= 0.0) {
  2299. k++;
  2300. if(k >= thiscutinbuf) {
  2301. done = 1;
  2302. break;
  2303. }
  2304. val = buf[k];
  2305. }
  2306. }
  2307. if(done)
  2308. break;
  2309. if(val < 0.0) {
  2310. newseglen = k - lastcutinbuf;
  2311. diff = newseglen - goalseglen;
  2312. if(abs(diff) < mindiff) { /* if a segment cut from here is closer to the goallength, mark it */
  2313. mindiff = abs(diff);
  2314. at = k + startsamp;
  2315. } else if(diff > 0) { /* if not closer, and already above goal length, finished */
  2316. break;
  2317. }
  2318. while(val < 0.0) {
  2319. k++;
  2320. if(k >= thiscutinbuf) {
  2321. done = 1;
  2322. break;
  2323. }
  2324. val = buf[k];
  2325. }
  2326. }
  2327. if(done)
  2328. break;
  2329. if(val == 0.0) {
  2330. while(val == 0.0) {
  2331. k++;
  2332. if(k >= thiscutinbuf)
  2333. break;
  2334. val = buf[k];
  2335. }
  2336. }
  2337. }
  2338. if(last_startsamp >= 0) { /* rejiggle bufs */
  2339. if((sndseekEx(dz->ifd[0],startsamp,0)<0)){
  2340. sprintf(errstr,"sndseek() failed\n");
  2341. return SYSTEM_ERROR;
  2342. }
  2343. dz->total_samps_read = startsamp;
  2344. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  2345. return(exit_status);
  2346. }
  2347. if(at) { /* if appropriate cutpoint found, mark it */
  2348. seg1 = (at - startsamp) - lastcutinbuf;
  2349. seg2 = thiscutinbuf - (at - startsamp);
  2350. rat = (double)seg1/(double)seg2;
  2351. if(rat < 2.0 && rat > .5) { /* if new cut is reasonable */
  2352. thiscut = cut[*cutcnt]; /* insert new cuts */
  2353. cut[*cutcnt] = at;
  2354. (*cutcnt)++;
  2355. cut[*cutcnt] = thiscut;
  2356. }
  2357. }
  2358. break;
  2359. }
  2360. }
  2361. return FINISHED;
  2362. }
  2363. /**************************** READ_VALIDPITCH_WSIZE_IN_SAMPS_FROM_BRKTABLE *****************************/
  2364. int read_validpitch_wsize_in_samps_from_brktable(double thistime,int kk,dataptr dz)
  2365. {
  2366. double dnval = 0.0, upval = 0.0, val, time;
  2367. double diff, mindiff = HUGE;
  2368. double dntimediff = -1.0, uptimediff = -1.0;
  2369. int n, m, wsize, here = 0;
  2370. for(n = 0,m = 0;n < dz->brksize[kk];n++,m+=2) {
  2371. time = dz->brk[kk][m];
  2372. if((diff = fabs(time - thistime)) < mindiff) {
  2373. mindiff = diff;
  2374. here = m;
  2375. }
  2376. n++;
  2377. }
  2378. time = dz->brk[kk][here];
  2379. val = dz->brk[kk][here+1];
  2380. if(val <= 0.0) { /* no pitch */
  2381. m = here;
  2382. m -= 2;
  2383. while(m >= 0) {
  2384. if((dnval = dz->brk[kk][m+1]) > 0.0) {
  2385. dntimediff = time - dz->brk[kk][m];
  2386. break;
  2387. }
  2388. m -= 2;
  2389. }
  2390. m = here;
  2391. m += 2;
  2392. while(m < (dz->brksize[kk] * 2)) {
  2393. if((upval = dz->brk[kk][m+1]) > 0.0) {
  2394. uptimediff = dz->brk[kk][m] - time;
  2395. break;
  2396. }
  2397. m += 2;
  2398. }
  2399. if(dntimediff < 0.0)
  2400. val = upval;
  2401. else if(uptimediff < 0.0)
  2402. val = dnval;
  2403. else if(uptimediff < dntimediff)
  2404. val = upval;
  2405. else
  2406. val = dnval;
  2407. }
  2408. wsize = (int)round((double)dz->infile->srate/val);
  2409. return wsize;
  2410. }
  2411. /**************************** NEXT_ZERO_CROSS *****************************/
  2412. int next_zero_cross(int here,dataptr dz)
  2413. {
  2414. float *buf = dz->sampbuf[0];
  2415. float val = buf[here];
  2416. while((val = buf[here]) >= 0.0)
  2417. here++;
  2418. return here;
  2419. }
  2420. /**************************** PREVIOUS_ZERO_CROSS *****************************/
  2421. int previous_zero_cross(int here,int firstzero,dataptr dz)
  2422. {
  2423. float *buf = dz->sampbuf[0];
  2424. float val;
  2425. while((val = buf[here]) < 0.0) {
  2426. here--;
  2427. if(here <= firstzero)
  2428. return firstzero;
  2429. }
  2430. here++;
  2431. return here;
  2432. }
  2433. /******************************** GET_ENVELOPE_TROUGHS ********************************/
  2434. int get_envelope_troughs(int *trofpnt,int *trofpntcnt,int envcnt,dataptr dz)
  2435. {
  2436. int n;
  2437. int lasttrofpntcnt = 0, realtrofpntcnt = 0, reallasttrofpntcnt = 0;
  2438. float lastenval;
  2439. int zerotrof;
  2440. trofpnt[0] = 0;
  2441. n = 1; /* time-val pairs : vals are odd numbers */
  2442. lastenval = dz->env[n];
  2443. if(lastenval <= 0.0) {
  2444. trofpnt[0] = 0; /* mark start of zero trough */
  2445. while(dz->env[n] <= 0.0) {
  2446. n+= 2;
  2447. if(n >= envcnt) {
  2448. sprintf(errstr,"NO PEAKS FOUND IN ENVELOPE\n");
  2449. return(GOAL_FAILED);
  2450. }
  2451. }
  2452. n -= 2;
  2453. if(n > 1) { /* if zero trough persists, also mark its end */
  2454. trofpnt[1] = n-1; /* times are even numbers : n is odd */
  2455. lastenval = dz->env[n];
  2456. *trofpntcnt = 1;
  2457. lasttrofpntcnt = 1;
  2458. }
  2459. n += 2;
  2460. } else {
  2461. n += 2;
  2462. while(n < envcnt) { /* GET FIRST ENVELOPE TROUGH */
  2463. if(dz->env[n] > lastenval) {
  2464. trofpnt[0] = 0;
  2465. lastenval = dz->env[n];
  2466. n+=2;
  2467. break;
  2468. } else if (dz->env[n] < lastenval) {
  2469. trofpnt[0] = n-1; /* times are even numbers : n is odd */
  2470. lastenval = dz->env[n];
  2471. n+=2;
  2472. break;
  2473. }
  2474. lastenval = dz->env[n];
  2475. n+=2;
  2476. }
  2477. }
  2478. if(n >= envcnt) {
  2479. sprintf(errstr,"NO PEAKS FOUND IN ENVELOPE\n");
  2480. return(GOAL_FAILED);
  2481. }
  2482. zerotrof = 0;
  2483. while(n < envcnt) { /* GET ENVELOPE TROUGHS */
  2484. if(dz->env[n] > lastenval) {
  2485. if(zerotrof) { /* mark and count end of a zero section */
  2486. *trofpntcnt = lasttrofpntcnt + 1;
  2487. trofpnt[*trofpntcnt] = n-3; /* times are even numbers : n is odd; previous time is a zeroval */
  2488. lasttrofpntcnt = *trofpntcnt; /* count end-of-a-zero-section: but don't count as a real (new) trof */
  2489. zerotrof = 0;
  2490. }
  2491. *trofpntcnt = lasttrofpntcnt + 1;
  2492. realtrofpntcnt = reallasttrofpntcnt + 1;
  2493. } else if (dz->env[n] < lastenval) { /* can't be in a zero block, as zero is min val */
  2494. trofpnt[*trofpntcnt] = n-1; /* times are even numbers : n is odd */
  2495. lasttrofpntcnt = *trofpntcnt;
  2496. reallasttrofpntcnt = realtrofpntcnt;
  2497. } else if(dz->env[n] <= 0.0) { /* dz->env[n] == previous value SO zero value is continued */
  2498. zerotrof = 1;
  2499. }
  2500. lastenval = dz->env[n];
  2501. n+=2;
  2502. }
  2503. if(realtrofpntcnt < 2) {
  2504. sprintf(errstr,"NO SIGNIFICANT PEAKS FOUND IN ENVELOPE\n");
  2505. return(GOAL_FAILED);
  2506. }
  2507. return(FINISHED);
  2508. }
  2509. /******************************** GET_TIME_NEAREST_TRUE_PITCH ********************************/
  2510. int get_time_nearest_true_pitch(double time,double *pitch,int kk,dataptr dz)
  2511. {
  2512. int n, no_up = 0, no_dn = 0, start;
  2513. double uptime=0.0, dntime, uppitch=0.0, dnpitch;
  2514. double *thisbrk = dz->brk[kk];
  2515. for(n=0;n<dz->brksize[kk] * 2;n+=2) {
  2516. if(thisbrk[n] >= time)
  2517. break;
  2518. }
  2519. if(n >= dz->brksize[kk] * 2) {
  2520. n--;
  2521. while(thisbrk[n] < 0.0)
  2522. n -= 2;
  2523. if(n<0) {
  2524. sprintf(errstr,"Pitch not found in pitch breakpoint file %d.\n",kk+1);
  2525. return(DATA_ERROR);
  2526. }
  2527. *pitch = thisbrk[n];
  2528. return FINISHED;
  2529. }
  2530. n++;
  2531. start = n;
  2532. while(thisbrk[n] < 0.0) {
  2533. n+= 2;
  2534. if(n >= dz->brksize[kk] * 2) {
  2535. no_up = 1;
  2536. break;
  2537. }
  2538. }
  2539. if(!no_up) {
  2540. uppitch = thisbrk[n];
  2541. uptime = thisbrk[n-1];
  2542. }
  2543. n = start;
  2544. while(thisbrk[n] < 0.0) {
  2545. n-= 2;
  2546. if(n < 0) {
  2547. no_dn = 1;
  2548. break;
  2549. }
  2550. }
  2551. if(no_up && no_dn) {
  2552. sprintf(errstr,"Pitch not found in pitch breakpoint file %d.\n",kk+1);
  2553. return(DATA_ERROR);
  2554. }
  2555. if(no_dn)
  2556. *pitch = uppitch;
  2557. else {
  2558. dnpitch = thisbrk[n];
  2559. dntime = thisbrk[n-1];
  2560. if(no_up)
  2561. *pitch = dnpitch;
  2562. else if((uptime - time) < (time - dntime))
  2563. *pitch = uppitch;
  2564. else
  2565. *pitch = dnpitch;
  2566. }
  2567. return FINISHED;
  2568. }
  2569. /******************************** COUNT_ZEROCROSSINGS ********************************/
  2570. int count_zerocrossings(int here,int there,float *buf)
  2571. {
  2572. int done = 0, isup = 0;
  2573. int zc_cnt = 0;
  2574. float val = buf[here];
  2575. while(here < there) {
  2576. while(flteq(val,0.0)) { /* only accessed if segment starts with zeros */
  2577. here++;
  2578. if(here >= there) {
  2579. done = 1;
  2580. break;
  2581. }
  2582. val = buf[here];
  2583. }
  2584. if(done)
  2585. break;
  2586. while(val >= 0.0) {
  2587. if(isup == -1)
  2588. zc_cnt++;
  2589. isup = 1;
  2590. here++;
  2591. if(here >= there) {
  2592. done = 1;
  2593. break;
  2594. }
  2595. val = buf[here];
  2596. }
  2597. if(done)
  2598. break;
  2599. while(val < 0.0) {
  2600. if(isup == 1)
  2601. zc_cnt++;
  2602. isup = -1;
  2603. here++;
  2604. if(here >= there) {
  2605. done = 1;
  2606. break;
  2607. }
  2608. val = buf[here];
  2609. }
  2610. }
  2611. return zc_cnt;
  2612. }
  2613. /******************************** TRIANGULATE_ENV ********************************
  2614. *
  2615. * Segment divided into 4 quarters, to define 3 overlapping areas...
  2616. *
  2617. * 1st quarter 2nd quarter 3rd quarter 4th quarter
  2618. * ___________ ___________ ___________ ___________
  2619. * | || || || |
  2620. *
  2621. * |______Env0______________||_____Env2_______________|
  2622. *
  2623. * |_____Env1_______________|
  2624. *
  2625. * Find area with minimum energy.
  2626. */
  2627. int triangulate_env(int *here,int *there,int ideal_place,float *buf)
  2628. {
  2629. int localhere = *here, localthere = *there;
  2630. int seglen, this_zc_cnt[3], max_zc_cnt;
  2631. int quartlen, quart[5], n, m;
  2632. int oversize, use_1st_quart = 0, use_last_quart = 0;
  2633. double qsum[4], esum[3];
  2634. seglen = localthere - localhere;
  2635. quartlen = seglen/4;
  2636. oversize = seglen - (quartlen * 4);
  2637. if(*here > ideal_place)
  2638. use_1st_quart = 1;
  2639. if(*there < ideal_place)
  2640. use_last_quart =1;
  2641. if(oversize) { /* func only called if >=5 zero crossings: so >= 9 samples: so 'there' never <= 'here' */
  2642. localhere++; /* truncate examined area by 1 sample */
  2643. if(oversize > 1)
  2644. localthere--; /* truncate examined area by 1 more sample */
  2645. if(oversize > 2)
  2646. localhere++; /* truncate examined area by 1 more sample */
  2647. }
  2648. quart[0] = localhere; /* divide segment into 4 equal parts */
  2649. for(n = 0; n < 4; n++)
  2650. quart[n+1] = quart[n] + quartlen;
  2651. if(use_1st_quart)
  2652. max_zc_cnt = count_zerocrossings(quart[0],quart[2],buf);
  2653. else if(use_last_quart)
  2654. max_zc_cnt = count_zerocrossings(quart[2],quart[4],buf);
  2655. else {
  2656. max_zc_cnt = -1;
  2657. for(n = 0; n < 3; n++) { /* Find zcross count in each of 3 overalpping Envs */
  2658. this_zc_cnt[n] = count_zerocrossings(quart[n],quart[n+2],buf);
  2659. if(this_zc_cnt[n] > max_zc_cnt)
  2660. max_zc_cnt = this_zc_cnt[n];
  2661. }
  2662. }
  2663. if(max_zc_cnt < 5) /* If none of the Env-segs has >= 5 zcrossings, return withot doing anything */
  2664. return max_zc_cnt; /* causing calling loop to finish */
  2665. if(use_1st_quart) {
  2666. *here = quart[0];
  2667. *there = quart[2];
  2668. return max_zc_cnt;
  2669. } else if(use_last_quart) {
  2670. *here = quart[2];
  2671. *there = quart[4];
  2672. return max_zc_cnt;
  2673. }
  2674. for(n = 0; n < 4; n++) { /* Sum the abs-samples in each Quarter */
  2675. qsum[n] = 0.0;
  2676. for(m = quart[n];m <quart[n+1];m++)
  2677. qsum[n] += fabs(buf[m]);
  2678. }
  2679. for(n = 0; n < 3; n++) /* Sum the abs-samples in each Env */
  2680. esum[n] = qsum[n] + qsum[n+1];
  2681. if((flteq(esum[0],esum[1])) && (flteq(esum[0],esum[2]))) { /* esums are all equal */
  2682. if(this_zc_cnt[1] >= 5) { /* return middle seg limits, unless too few zcrossings */
  2683. *here = quart[1];
  2684. *there = quart[3];
  2685. return this_zc_cnt[1];
  2686. } else if(this_zc_cnt[0] >= 5) { /* else return start seg limits, unless too few zcrossings */
  2687. *here = quart[0];
  2688. *there = quart[2];
  2689. return this_zc_cnt[0];
  2690. } else { /* else return end seg limits */
  2691. *here = quart[2];
  2692. *there = quart[4];
  2693. return this_zc_cnt[2];
  2694. }
  2695. } else if((esum[0] <= esum[1]) && (esum[0] <= esum[2])) { /* esum[0] in Env0 has minimum energy */
  2696. if(this_zc_cnt[0] >= 5) { /* If Env0 has > 5 zcrossings */
  2697. *here = quart[0]; /* define this as the new working segment in which to find min energy */
  2698. *there = quart[2]; /* Else return without doing anything */
  2699. } /* (Calling process then drops out & uses segment we had at start of this func) */
  2700. return this_zc_cnt[0];
  2701. } else if((esum[1] <= esum[0]) && (esum[1] <= esum[2])) { /* esum[1] in Env1 has minimum energy */
  2702. if(this_zc_cnt[1] >= 5) {
  2703. *here = quart[1];
  2704. *there = quart[3];
  2705. }
  2706. return this_zc_cnt[1];
  2707. } /* else */ /* esum[2] in Env2 has minimum energy */
  2708. if(this_zc_cnt[2] >= 5) {
  2709. *here = quart[2];
  2710. *there = quart[4];
  2711. }
  2712. return this_zc_cnt[2];
  2713. }
  2714. /******************************** MARK_CUT ********************************/
  2715. int mark_cut(int *cutcnt,int *cut,int localpeakcnt,double *startarray,int here,int there,
  2716. int startsamp,int first_downcross,double starttime,int msg,dataptr dz)
  2717. {
  2718. double localpeak1, localpeak2, localpeak3, maxlocalpeak, minenergy, energy;
  2719. int localpeakat1, localpeakat2 , at = 0, k, m, thissampinbuf;
  2720. int up;
  2721. double *localpeak = startarray;
  2722. switch(localpeakcnt) {
  2723. case(0):
  2724. if(msg)
  2725. sprintf(errstr,"FAILED TO LOCATE CUT POINT NEAR %lf secs: NO LOCAL PEAK FOUND: IMPOSSIBLE!!\n",starttime);
  2726. return(PROGRAM_ERROR);
  2727. case(1): /* SINGLE PEAK */
  2728. cut[*cutcnt] = here + startsamp; /* return location of zero crossing after peak */
  2729. break;
  2730. case(2): /* TWO PEAKS */
  2731. if(*localpeak > 0.0) { /* FIRST PEAK IS ABOVE ZERO: find downcross after this */
  2732. here = (int)round(*(localpeak+1)); /* location of 1st local peak */
  2733. here -= startsamp; /* location in buf */
  2734. here = next_zero_cross(here,dz); /* find following down-zerocross */
  2735. cut[*cutcnt] = here + startsamp; /* return its absolute location */
  2736. } else { /* FIRST PEAK IS BELOW ZERO */
  2737. if(fabs(*localpeak) < *(localpeak+2)) /* initial peak is lower energy */
  2738. cut[*cutcnt] = here + startsamp; /* return absolute-position of its start */
  2739. cut[*cutcnt] = there + startsamp; /*final peak is lower energy, return absolute-pos of its end */
  2740. }
  2741. break;
  2742. case(3):
  2743. localpeak1 = *localpeak++; /* THREE PEAKS */
  2744. localpeakat1 = (int)round(*localpeak++); /* Find location of (abs) max of the 3 */
  2745. maxlocalpeak = *localpeak;
  2746. at = 1;
  2747. localpeak2 = *localpeak++;
  2748. localpeakat2 = (int)round(*localpeak++);
  2749. if(localpeak2 > maxlocalpeak) {
  2750. maxlocalpeak = localpeak2;
  2751. at = 2;
  2752. }
  2753. localpeak3 = *localpeak++;
  2754. if(localpeak3 > maxlocalpeak) {
  2755. maxlocalpeak = localpeak3;
  2756. at = 3;
  2757. }
  2758. up = 0; /* Is first peak +ve or -ve */
  2759. if(localpeak1 > 0.0)
  2760. up = 1;
  2761. switch(at) { /* Select on basis of where max peak is */
  2762. case(1): /* 1st peak is max */
  2763. if(up) {
  2764. cut[*cutcnt] = there + startsamp; /* +ve cycle, return end of last peak */
  2765. } else {
  2766. here = localpeakat2 - startsamp;
  2767. here = next_zero_cross(here,dz); /* -ve cycle, return zero after peak2 */
  2768. cut[*cutcnt] = here + startsamp;
  2769. }
  2770. break;
  2771. case(2): /* 2nd peak is max */
  2772. if(localpeak1 > localpeak3) { /* 3rd peak is minimum */
  2773. if(up) {
  2774. cut[*cutcnt] = there + startsamp; /* +ve cycle, return end of peak3 */
  2775. } else {
  2776. here = localpeakat2 - startsamp;
  2777. here = next_zero_cross(here,dz); /* -ve cycle, return start of peak3 */
  2778. cut[*cutcnt] = here + startsamp;
  2779. }
  2780. } else { /* 1st peak is minimum */
  2781. if(up) {
  2782. here = localpeakat1 - startsamp;
  2783. here = next_zero_cross(here,dz); /* +ve cycle, return end of peak1 */
  2784. cut[*cutcnt] = here + startsamp;
  2785. } else {
  2786. cut[*cutcnt] = here + startsamp; /* -ve cycle, return start of peak1 */
  2787. }
  2788. }
  2789. break;
  2790. case(3): /* 3rd peak is max */
  2791. if(up) {
  2792. here = localpeakat1 - startsamp;
  2793. here = next_zero_cross(here,dz); /* +ve cycle, return end of peak1 */
  2794. cut[*cutcnt] = here + startsamp;
  2795. } else {
  2796. cut[*cutcnt] = here + startsamp; /* -ve cycle, return start of peak1 */
  2797. }
  2798. break;
  2799. }
  2800. break;
  2801. default: /* MORE THAN 3 PEAKS */
  2802. localpeak = startarray;
  2803. minenergy = HUGE; /* find minimum energy of each PAIR of peaks */
  2804. for(k = 0,m = 2; m < localpeakcnt * 2; k+=2,m+=2) {
  2805. energy = fabs(localpeak[k]) + fabs(localpeak[m]);
  2806. if(energy < minenergy) {
  2807. minenergy = energy;
  2808. at = k;
  2809. }
  2810. }
  2811. thissampinbuf = (int)round(localpeak[at+1]);
  2812. thissampinbuf -= startsamp;
  2813. if(localpeak[at] > 0.0) { /* if min energy is at a pair that starts +ve */
  2814. thissampinbuf = next_zero_cross(thissampinbuf,dz);
  2815. cut[*cutcnt] = thissampinbuf + startsamp; /* return end of that pair's 1st peak */
  2816. } else {
  2817. thissampinbuf = previous_zero_cross(thissampinbuf,first_downcross,dz);
  2818. cut[*cutcnt] = thissampinbuf + startsamp; /* else return start of that pair's 1st peak */
  2819. }
  2820. }
  2821. return(FINISHED);
  2822. }
  2823. /******************************** FIND_THE_LOCAL_PEAKS ********************************/
  2824. int find_the_local_peaks(int *here,int *there,float *buf,int *n,int trofpntcnt,int *trofpnt,
  2825. int *startsamp,int *endsamp,int losamp, int *cut, int cutcnt, double *localpeak, double *scanarray,
  2826. int *localpeakcnt,int *first_downcross,dataptr dz)
  2827. {
  2828. int exit_status, notfound = 0, finished = 0, bufinc = 0;
  2829. int maxat=0;
  2830. float maxval=0.0f, val;
  2831. int wsize, hisamp,losampinbuf,hisampinbuf;
  2832. int orighere, origthere;
  2833. *first_downcross = -1;
  2834. wsize = *there - *here;
  2835. while(!finished) {
  2836. hisamp = min(dz->insams[0],losamp + wsize); /* get end-of-search area from wtime & half-wsize */
  2837. if(hisamp >= dz->insams[0])
  2838. hisamp = dz->insams[0];
  2839. losampinbuf = losamp - *startsamp; /* get search ends relative to buffer */
  2840. hisampinbuf = hisamp - *startsamp;
  2841. if(hisampinbuf >= dz->buflen) {
  2842. if((sndseekEx(dz->ifd[0],losamp,0)<0)){
  2843. sprintf(errstr,"sndseek() failed\n");
  2844. return SYSTEM_ERROR;
  2845. }
  2846. dz->total_samps_read = losamp;
  2847. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  2848. return(exit_status);
  2849. *endsamp = dz->total_samps_read;
  2850. *startsamp = *endsamp - dz->ssampsread;
  2851. losampinbuf = losamp - *startsamp; /* get search ends relative to buffer */
  2852. hisampinbuf = hisamp - *startsamp;
  2853. bufinc = 0;
  2854. }
  2855. *here = losampinbuf;
  2856. /* IGNORE EDGES OF WINDOW before the first, and after the last, zero crossing */
  2857. /* MOVE START SEARCH TO FIRST ZERO CROSSING */
  2858. if(!bufinc) {
  2859. val = buf[*here];
  2860. *first_downcross = -1;
  2861. if(val >= 0.0) {
  2862. while(val >= 0.0) {
  2863. (*here)++;
  2864. if(*here >= hisampinbuf) {
  2865. notfound = 1; /* no zero-cross found */
  2866. break;
  2867. }
  2868. val = buf[*here];
  2869. }
  2870. if(notfound) {
  2871. wsize += 20; /* no zero-cross found, return to loop head */
  2872. bufinc = 1;
  2873. continue; /* and move end of search window */
  2874. }
  2875. // VAL is just after zero cross downwards
  2876. *first_downcross = *here; /* mark 1st down-zerocross in search area */
  2877. } else if (val <= 0.0) {
  2878. while(val <= 0.0) {
  2879. (*here)++;
  2880. if(*here >= hisampinbuf) {
  2881. notfound = 1; /* no zero-cross found */
  2882. break;
  2883. }
  2884. val = buf[*here];
  2885. }
  2886. if(notfound) {
  2887. wsize += 20; /* no zero-cross found, return to loop head */
  2888. bufinc = 1;
  2889. continue;
  2890. }
  2891. // VAL is just after zero cross upwards
  2892. }
  2893. }
  2894. /* MOVE END OF SEARCH TO LAST ZERO CROSSING */
  2895. *there = hisampinbuf - 1;
  2896. val = buf[*there];
  2897. if(val >= 0.0) {
  2898. //below = 0;
  2899. while(val >= 0.0) {
  2900. (*there)--;
  2901. if(*there < losampinbuf) {
  2902. break;
  2903. }
  2904. val = buf[*there];
  2905. }
  2906. } else if(val <= 0.0) {
  2907. //below = 1;
  2908. while(val <= 0.0) {
  2909. (*there)--;
  2910. if(*there < losampinbuf) {
  2911. break;
  2912. }
  2913. val = buf[*there];
  2914. }
  2915. }
  2916. if(*there <= *here) { /* There is ONLY ONE zero-crossing found */
  2917. if(buf[*here] >= 0.0) { /* This is an upward-crossing zero, NOT a downward crossing zero */
  2918. notfound = 1; /* no DOWN-zero-cross found, return to loop head */
  2919. wsize += 20;
  2920. bufinc = 1;
  2921. continue; /* and move end of search window */
  2922. }
  2923. cut[cutcnt] = *here + *startsamp; /* return the single downward-crossing zero */
  2924. *first_downcross = *here;
  2925. dz->zeroset = 1;
  2926. return FINISHED;
  2927. } /* ELSE more than one zero-cross found */
  2928. /* therefore at least one intervening (+ or -) peak exists */
  2929. (*there)++; /* move end search to the value AFTER the last zero-crossing */
  2930. finished = 1; /* break from search loop */
  2931. }
  2932. orighere = *here;
  2933. origthere = *there;
  2934. /* STORE PEAKS BETWEEN ZERO-CROSSINGS */
  2935. val = buf[*here];
  2936. while(*here < *there) {
  2937. if(val >= 0.0) {
  2938. maxval = val;
  2939. maxat = *here;
  2940. while(val >= 0.0) {
  2941. (*here)++;
  2942. if(*here >= *there)
  2943. break;
  2944. val = buf[*here];
  2945. if(val > maxval) {
  2946. maxval = val;
  2947. maxat = *here;
  2948. }
  2949. }
  2950. } else if(val <= 0.0) {
  2951. maxval = val;
  2952. maxat = *here;
  2953. while(val <= 0.0) {
  2954. (*here)++;
  2955. if(*here >= *there)
  2956. break;
  2957. val = buf[*here];
  2958. if(val < maxval) {
  2959. maxval = val;
  2960. maxat = *here;
  2961. }
  2962. }
  2963. }
  2964. if(*first_downcross < 0)
  2965. dz->zeroset = 1;
  2966. if((maxval > 0.0) && (*first_downcross < 0))
  2967. *first_downcross = *here;
  2968. *localpeak++ = (double)maxval;
  2969. *localpeak++ = (double)(maxat + *startsamp);
  2970. }
  2971. *localpeakcnt = (localpeak - scanarray)/2;
  2972. if(*localpeakcnt == 1) {
  2973. if(!dz->zeroset) { /* If only 1 peak, the cut points are at the first_downcross if NOT zeroset */
  2974. *here = *first_downcross;
  2975. } else {
  2976. *here = orighere; // REDUNDANT, as, if dz->zeroset then "mark_cut" is not called.
  2977. *there = origthere;
  2978. }
  2979. }
  2980. return CONTINUE;
  2981. }
  2982. /***************************** SMOOTH_CUTS *****************************/
  2983. int smooth_cuts(int *cut,int *cutcnt,int cutstart,dataptr dz)
  2984. {
  2985. int exit_status;
  2986. int n, k, seg0, seg1, seg2, minseg, end, start, *thiscut, srchlen, minlen;
  2987. int pitchseglim, pitchseglo=0, realend, lastcutval;
  2988. double pitchseg, lastpitchseg=0.0, time, big_seg, this_seg, last_seg, big_int, this_int, last_int;
  2989. int last_cut, this_cut, next_cut;
  2990. double last_ratio, next_ratio;
  2991. if((sndseekEx(dz->ifd[0],0,0)<0)){
  2992. sprintf(errstr,"sndseek() failed\n");
  2993. return SYSTEM_ERROR;
  2994. }
  2995. dz->total_samps_read = 0;
  2996. if((exit_status = read_samps(dz->sampbuf[0],dz))<0)
  2997. return(exit_status);
  2998. for(n=3 + cutstart;n<*cutcnt;n++) {
  2999. lastcutval = 0;
  3000. end = cut[n];
  3001. realend = end;
  3002. time = (double)cut[n-3]/(double)dz->infile->srate;
  3003. if((exit_status = read_value_from_brktable(time,0,dz))<0)
  3004. return(exit_status); /* Get pitch at start of cut segment */
  3005. if(dz->param[0] > 0.0) { /* if it's a true pitch ... */
  3006. pitchseg = (double)dz->infile->srate/dz->param[0]; /* Find corresponding segment length */
  3007. pitchseglim = (int)round(pitchseg * ALMOST_OCT); /* Go to almost an 8va up */
  3008. pitchseglo = (int)round(pitchseg/ALMOST_OCT); /* Go to almost an 8va down */
  3009. pitchseglim += cut[n-3]; /* Prevent autocorrelation-search going beyond 8va */
  3010. if(end > pitchseglim) {
  3011. end = pitchseglim; /* Typically, end of search is ~2* expected pitchseg len */
  3012. lastcutval = cut[n-2]; /* & we save origval in case new val is to be INTERPOLATED. */
  3013. } /* But if 3segs is smaller, set endofsearch to endof 3segs */
  3014. } else
  3015. pitchseg = -1.0;
  3016. start = cut[n-3];
  3017. thiscut = &(cut[n-2]);
  3018. seg0 = cut[n-2] - cut[n-3];
  3019. seg1 = cut[n-1] - cut[n-2];
  3020. seg2 = cut[n] - cut[n-1];
  3021. minseg = min(seg0,seg1);
  3022. minseg = min(minseg,seg2);
  3023. srchlen = cut[n] - cut[n-3];
  3024. if((minlen = minseg/2) <= 0) /* if previous segs tiny, e.g. just 1 seg, this val gets 0 */
  3025. minlen = min(srchlen/6,pitchseglo); /* use either ~8va below pitch, or half the average of 3seglen */
  3026. if(n >= 3) {
  3027. last_cut = cut[n-2] - cut[n-3];
  3028. this_cut = cut[n-1] - cut[n-2];
  3029. next_cut = cut[n] - cut[n-1];
  3030. if(((last_cut > this_cut) && (next_cut > this_cut)) || ((last_cut < this_cut) && (next_cut < this_cut))) {
  3031. if(last_cut > this_cut) {
  3032. last_ratio = (double)last_cut/(double)this_cut;
  3033. next_ratio = (double)next_cut/(double)this_cut;
  3034. } else {
  3035. last_ratio = (double)this_cut/(double)last_cut;
  3036. next_ratio = (double)this_cut/(double)next_cut;
  3037. }
  3038. if((last_ratio > 1.3) || (next_ratio > 1.3)) {
  3039. if((exit_status = auto_correlate(start,thiscut,end,realend,minlen,pitchseg,0,dz))<0)
  3040. return(exit_status);
  3041. }
  3042. }
  3043. }
  3044. if(cut[n-2] >= cut[n-1]) { /* If next cut is now too near to new cut ... */
  3045. for(k = n;k<*cutcnt;k++) /* e.g. 0 20 30 40 --> 0 20 40 40 .... omit duplicate */
  3046. cut[k-1] = cut[k]; /* OR 0 20 30 40 --> 0 20 50 40 .... omit skipped val */
  3047. (*cutcnt)--;
  3048. n--;
  3049. } else if(lastcutval > 0) { /* If new cut will fit between previous, and original value here */
  3050. /* e.g. originally 20 [200] 220 240 --> 20 40 220 240 (200 stored as lastcutval) */
  3051. if(lastcutval - cut[n-2] > pitchseglo) {
  3052. for(k = *cutcnt;k>=n-1;k--) /* then reinsert orig val .... */
  3053. cut[k+1] = cut[k]; /* e.g. 20 40 220 240 --> 20 40 200 220 240 */
  3054. cut[n-1] = lastcutval;
  3055. (*cutcnt)++;
  3056. }
  3057. } /* Eliminate segs that are 8va up (twice too short) */
  3058. if((n > cutstart+3) && (lastpitchseg > 0.0) && (pitchseg > 0.0)) {
  3059. pitchseg = (pitchseg + lastpitchseg)/2.0;
  3060. this_seg = (double)(cut[n-2] - cut[n-3]);
  3061. if((big_seg = (double)(cut[n-2] - cut[n-4])) > pitchseg)
  3062. big_int = big_seg/pitchseg;
  3063. else
  3064. big_int = pitchseg/big_seg;
  3065. if(this_seg > pitchseg)
  3066. this_int = this_seg/pitchseg;
  3067. else
  3068. this_int = pitchseg/this_seg;
  3069. if((last_seg = (double)(cut[n-3] - cut[n-4])) > pitchseg)
  3070. last_int = last_seg/pitchseg;
  3071. else
  3072. last_int = pitchseg/last_seg;
  3073. if((big_int < this_int) && (big_int < last_int)) {
  3074. for(k = n-2;k < *cutcnt;k++)
  3075. cut[k-1] = cut[k];
  3076. (*cutcnt)--;
  3077. n--;
  3078. }
  3079. }
  3080. lastpitchseg = pitchseg;
  3081. }
  3082. return FINISHED;
  3083. }
  3084. /******************************** AUTO_CORRELATE ********************************
  3085. * *at
  3086. * (cut to search realend
  3087. * start adjust) end of 3segs
  3088. * ___________ ______ _____________i___________
  3089. * | | | i |
  3090. * i
  3091. *
  3092. *
  3093. *
  3094. * start = start of the segment.
  3095. * end = end of the search area for correlation between segs.
  3096. * *at = starts out as the original cut position, and may be changed by this process.
  3097. * realend = end of the group of 3 segs: if no cutsite found before 'end', extend search towards 'realend'
  3098. * (cutsites are always at downward-crossing zeros)
  3099. * minlen = minimum length of adjacent stretches of sound to compare
  3100. * pitchseg = length of seg corresponding to pitch (if any) at this place.
  3101. * if the new cutpoint is further from the pitchseg val than the original cut (*at)
  3102. * the search can be restricted to a smaller range then defiend by 'end'.
  3103. */
  3104. int auto_correlate(int start,int *at,int end,int realend,int minlen,double pitchseg,int kk,dataptr dz)
  3105. {
  3106. float *buf = dz->sampbuf[0];
  3107. int startbuf = 0, startinbuf, atinbuf, orig_atinbuf, maxinbuf, n, m, oldlen, newlen;
  3108. int newlen2=0, atinbuf2, orig_maxinbuf;
  3109. double max_auto, max_auto2, thisauto, time;
  3110. int finished, unpitched = 0, extended = 0;
  3111. if(end > dz->total_samps_read) {
  3112. if((sndseekEx(dz->ifd[kk],start,0)<0)){
  3113. sprintf(errstr,"sndseek() failed\n");
  3114. return SYSTEM_ERROR;
  3115. }
  3116. dz->total_samps_read = start;
  3117. dz->samps_left = dz->insams[kk] - start;
  3118. if((dz->ssampsread = fgetfbufEx(dz->sampbuf[0], dz->buflen,dz->ifd[kk],0)) < 0) {
  3119. sprintf(errstr,"Can't read samples from input soundfile %d\n",kk+1);
  3120. return(SYSTEM_ERROR);
  3121. }
  3122. dz->total_samps_read += dz->ssampsread;
  3123. dz->samps_left -= dz->ssampsread;
  3124. }
  3125. //NEW
  3126. startbuf = dz->total_samps_read - dz->ssampsread;
  3127. startinbuf = start - startbuf;
  3128. atinbuf = *at - startbuf;
  3129. maxinbuf = end - startbuf;
  3130. orig_atinbuf = atinbuf;
  3131. orig_maxinbuf = maxinbuf;
  3132. finished = 0;
  3133. // oldlen = *at - startinbuf;
  3134. oldlen = atinbuf - startinbuf;
  3135. do {
  3136. while(!finished) {
  3137. atinbuf2 = -1;
  3138. n = startinbuf;
  3139. m = startinbuf + minlen;
  3140. m = next_down_zcross(m,maxinbuf,buf); /* starting with a segment which ends at first down_zcross after minlen */
  3141. if(m > maxinbuf || m < 0)
  3142. break;
  3143. max_auto = autocorrelate(n,m,buf); /* autocorrelate two minsize segments */
  3144. max_auto2 = max_auto;
  3145. atinbuf = m;
  3146. for(;;) { /* gradually expand size to next (etc) down_zcross, & autocorrelate */
  3147. if((m = next_down_zcross(m,maxinbuf,buf)) < 0)
  3148. break;
  3149. if((thisauto = autocorrelate(n,m,buf)) > max_auto) {
  3150. max_auto = thisauto;
  3151. atinbuf = m;
  3152. } else if(thisauto > max_auto2) {
  3153. max_auto2 = thisauto;
  3154. atinbuf2 = m; /* Save best and 2nd best lengths (tested by correlation) */
  3155. }
  3156. }
  3157. if(pitchseg < 0.0) { /* If an unpitched seg, use closest pitch to set arbitrary 'ideal' seg size */
  3158. unpitched = 1;
  3159. time = (double)(*at)/(double)dz->infile->srate;
  3160. pitchseg = (double)read_validpitch_wsize_in_samps_from_brktable(time,kk,dz);
  3161. }
  3162. newlen = atinbuf - startinbuf;
  3163. if(atinbuf2 >= 0)
  3164. newlen2 = atinbuf2 - startinbuf;
  3165. *at = atinbuf + startbuf; /* Compare best-correlated cuts, with existing cut */
  3166. if(fabs((double)newlen - pitchseg) <= fabs((double)oldlen - pitchseg)) {
  3167. if(atinbuf2 >= 0) { /* If 2nd best correlation point exists & is closer to pitch than best, use it */
  3168. if(fabs((double)newlen2 - pitchseg) < fabs((double)newlen - pitchseg))
  3169. *at = atinbuf2 + startbuf;
  3170. } /* Else, If best new value is closer to pitch than original: use it */
  3171. return FINISHED;
  3172. /* If best cut(s) are worse than existing cut, */
  3173. } else if(extended) { /* if already EXTENDED the search, no point in looking at smaller range */
  3174. *at = orig_atinbuf + startbuf; /* Reset, and break from inner ('while') loop */
  3175. break;
  3176. } else { /* Otherwise, set end of search to the down_zcross PRIOR to the one found */
  3177. maxinbuf = last_down_zcross(maxinbuf,startinbuf,buf);
  3178. if(maxinbuf <= 0) { /* If can't get any smaller, break from inner 'while' loop */
  3179. *at = orig_atinbuf + startbuf;
  3180. break;
  3181. } /* Otherwise continue search in 'while' loop */
  3182. }
  3183. if(unpitched)
  3184. pitchseg = -1.0;
  3185. } /* If inner loop search has failed */
  3186. if(end < realend) { /* if the search end is less than the realend of the 3segments, EXTEND the search */
  3187. maxinbuf = next_down_zcross(orig_maxinbuf,dz->buflen,buf);
  3188. if(maxinbuf < 0)
  3189. break;
  3190. end = maxinbuf + startbuf;
  3191. orig_maxinbuf = maxinbuf;
  3192. extended = 1;
  3193. }
  3194. } while(end < realend);
  3195. return FINISHED;
  3196. }
  3197. /******************************** AUTOCORRELATE ********************************/
  3198. double autocorrelate(int n,int m,float *buf)
  3199. {
  3200. int j, k;
  3201. double sum = 0.0;
  3202. for(j = n,k = m;j<m;j++,k++)
  3203. sum += (buf[j] * buf[k]);
  3204. sum = sum/(double)(m-n);
  3205. return sum;
  3206. }
  3207. /******************************** NEXT_DOWN_ZCROSS ********************************/
  3208. int next_down_zcross(int here,int hibound,float *buf)
  3209. {
  3210. double val = buf[here];
  3211. while(val <= 0.0) {
  3212. here++;
  3213. if(here >= hibound)
  3214. return -1;
  3215. val = buf[here];
  3216. }
  3217. while(val > 0.0) {
  3218. here++;
  3219. if(here >= hibound)
  3220. return -1;
  3221. val = buf[here];
  3222. }
  3223. return here;
  3224. }
  3225. /******************************** LAST_DOWN_ZCROSS ********************************/
  3226. int last_down_zcross(int here,int lobound,float *buf)
  3227. {
  3228. double val = buf[here];
  3229. while(val <= 0.0) {
  3230. here--;
  3231. if(here < lobound)
  3232. return -1;
  3233. val = buf[here];
  3234. }
  3235. while(val >= 0.0) {
  3236. here--;
  3237. if(here < lobound)
  3238. return -1;
  3239. val = buf[here];
  3240. }
  3241. while(val < 0.0) {
  3242. here--;
  3243. if(here < lobound)
  3244. return -1;
  3245. val = buf[here];
  3246. }
  3247. here++;
  3248. return here;
  3249. }
  3250. /*************************** GET_FOFEX_EXCLUDE_DATA ***********************/
  3251. int get_fofex_exclude_data(char *filename,dataptr dz)
  3252. {
  3253. FILE *fp;
  3254. double dummy;
  3255. int *time, lasttime = 0, cnt;
  3256. char temp[200], temp2[4], *q;
  3257. if(sloom) {
  3258. temp[0] = NUMERICVAL_MARKER;
  3259. temp[1] = ENDOFSTR;
  3260. temp2[0] = filename[0];
  3261. temp2[1] = ENDOFSTR;
  3262. if(!strcmp(temp2,temp)) {
  3263. dz->itemcnt = 0;
  3264. return FINISHED;
  3265. }
  3266. } else {
  3267. if(!strcmp(filename,"0")) {
  3268. dz->itemcnt = 0;
  3269. return FINISHED;
  3270. }
  3271. }
  3272. if((fp = fopen(filename,"r"))==NULL) {
  3273. sprintf(errstr, "Can't open file %s to read data.\n",filename);
  3274. return(DATA_ERROR);
  3275. }
  3276. cnt = 0;
  3277. while(fgets(temp,200,fp)==temp) {
  3278. q = temp;
  3279. while(get_float_from_within_string(&q,&dummy)) {
  3280. cnt++;
  3281. }
  3282. }
  3283. if(cnt == 0) {
  3284. sprintf(errstr,"No data in file %s\n",filename);
  3285. return(DATA_ERROR);
  3286. }
  3287. if(((dz->itemcnt = cnt/2) * 2) != cnt) {
  3288. sprintf(errstr,"Data not paired correctly in file %s\n",filename);
  3289. return(DATA_ERROR);
  3290. }
  3291. if((dz->lparray[0] = (int *)malloc(cnt * sizeof(int)))==NULL) {
  3292. sprintf(errstr,"INSUFFICIENT MEMORY for data in file %s.\n",filename);
  3293. return(MEMORY_ERROR);
  3294. }
  3295. time = dz->lparray[0];
  3296. rewind(fp);
  3297. lasttime = -1;
  3298. while(fgets(temp,200,fp)==temp) {
  3299. q = temp;
  3300. while(get_float_from_within_string(&q,&dummy)) {
  3301. *time = (int)round(dummy);
  3302. if(*time <= lasttime) {
  3303. sprintf(errstr,"Times (%d & %d) in file %s are not in increasing order.\n",
  3304. lasttime,*time,filename);
  3305. return(DATA_ERROR);
  3306. }
  3307. lasttime = *time;
  3308. time++;
  3309. }
  3310. }
  3311. if(fclose(fp)<0) {
  3312. fprintf(stdout,"WARNING: Failed to close file %s.\n",filename);
  3313. fflush(stdout);
  3314. }
  3315. return(FINISHED);
  3316. }
  3317. /*************************** GET_FOFBANK_INFO ***********************/
  3318. int get_fofbank_info(char *filename,dataptr dz)
  3319. {
  3320. FILE *fp;
  3321. double dummy;
  3322. int pos, lastpos=0, dur, lastdur=0, cnt;
  3323. int *vals;
  3324. char temp[200], *q;
  3325. int ispos = 1;
  3326. if((fp = fopen(filename,"r"))==NULL) {
  3327. sprintf(errstr, "Can't open file %s to read data.\n",filename);
  3328. return(DATA_ERROR);
  3329. }
  3330. cnt = 0;
  3331. while(fgets(temp,200,fp)==temp) {
  3332. q = temp;
  3333. while(get_float_from_within_string(&q,&dummy))
  3334. cnt++;
  3335. }
  3336. if(cnt == 0) {
  3337. sprintf(errstr,"No data in file %s\n",filename);
  3338. return(DATA_ERROR);
  3339. }
  3340. if(((dz->itemcnt = cnt/2) * 2) != cnt) {
  3341. sprintf(errstr,"Data not paired correctly in file %s\n",filename);
  3342. return(DATA_ERROR);
  3343. }
  3344. if((dz->lparray[0] = (int *)malloc(cnt * sizeof(int)))==NULL) {
  3345. sprintf(errstr,"INSUFFICIENT MEMORY for data in file %s.\n",filename);
  3346. return(MEMORY_ERROR);
  3347. }
  3348. vals = dz->lparray[0];
  3349. rewind(fp);
  3350. cnt = 0;
  3351. while(fgets(temp,200,fp)==temp) {
  3352. q = temp;
  3353. while(get_float_from_within_string(&q,&dummy)) {
  3354. if(ispos) {
  3355. pos = (int)round(dummy);
  3356. if(cnt>0) {
  3357. if(pos < lastpos) {
  3358. sprintf(errstr,"FOF position info out of sequence in file %s (should increase).\n",filename);
  3359. return(MEMORY_ERROR);
  3360. }
  3361. }
  3362. lastpos = pos;
  3363. vals[cnt] = pos;
  3364. } else {
  3365. dur = (int)round(dummy);
  3366. if(cnt>1) {
  3367. if(lastdur <= dur) {
  3368. sprintf(errstr,"FOF duration info out of sequence in file %s (should decrease). Possibly zeros in pitch data.\n",filename);
  3369. return(MEMORY_ERROR);
  3370. }
  3371. }
  3372. lastdur = dur;
  3373. vals[cnt] = dur;
  3374. }
  3375. ispos = !ispos;
  3376. cnt++;
  3377. }
  3378. }
  3379. if(fclose(fp)<0) {
  3380. fprintf(stdout,"WARNING: Failed to close file %s.\n",filename);
  3381. fflush(stdout);
  3382. }
  3383. return(FINISHED);
  3384. }
  3385. /**************************************** CREATE_PICHSTEPS ****************************************
  3386. *
  3387. * Create array of sampcnts correspnoding to each degree of chromatic scale in required range
  3388. */
  3389. int create_pitchsteps_semitone_info(double lopch,double hipch,int **pitchstep,int *outcnt,double srate)
  3390. {
  3391. int n;
  3392. double lofrq;
  3393. int lopich = (int)ceil(lopch);
  3394. int hipich = (int)ceil(hipch);
  3395. n = 1;
  3396. while (lopich <= hipich) {
  3397. if(n >= *outcnt)
  3398. return(PROGRAM_ERROR);
  3399. lofrq = miditohz((double)lopich);
  3400. (*pitchstep)[n] = (int)round(srate/lofrq);
  3401. lopich++;
  3402. n += 2;
  3403. }
  3404. *outcnt = n - 1; // ENSURES ARRAY IS TRUNCATED TO CORRECT SIZE
  3405. return FINISHED;
  3406. }
  3407. /************************* SETUP_FOFEX_PARAM_RANGES_AND_DEFAULTS *******************/
  3408. int setup_fofex_param_ranges_and_defaults(dataptr dz)
  3409. {
  3410. int exit_status;
  3411. aplptr ap = dz->application;
  3412. // set_param_ranges()
  3413. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  3414. // NB total_input_param_cnt is > 0 !!!s
  3415. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  3416. return(FAILED);
  3417. // get_param_ranges()
  3418. switch(dz->process) {
  3419. case(FOFEX_EX):
  3420. ap->lo[0] = -2.0;
  3421. ap->hi[0] = dz->nyquist;
  3422. ap->default_val[0] = 440.0;
  3423. if(dz->mode == 1) {
  3424. ap->lo[1] = 0.0;
  3425. ap->hi[1] = dz->duration;
  3426. ap->default_val[1] = 0.0;
  3427. } else { // dB level
  3428. ap->lo[1] = -60.0;
  3429. ap->hi[1] = 0.0;
  3430. ap->default_val[1] = 0.0;
  3431. }
  3432. ap->lo[2] = 1;
  3433. ap->hi[2] = 16;
  3434. ap->default_val[2] = 1;
  3435. dz->maxmode = 3;
  3436. break;
  3437. case(FOFEX_CO):
  3438. if(dz->mode == FOF_MEASURE)
  3439. break;
  3440. ap->lo[0] = -2.0;
  3441. ap->hi[0] = dz->nyquist;
  3442. ap->default_val[0] = 440.0;
  3443. ap->lo[1] = 0;
  3444. ap->hi[1] = 1;
  3445. ap->default_val[1] = 1;
  3446. ap->lo[2] = 0;
  3447. ap->hi[2] = 2;
  3448. ap->default_val[2] = 1;
  3449. if(dz->mode == FOF_SINGLE) {
  3450. ap->lo[3] = 1;
  3451. ap->hi[3] = 1024;
  3452. ap->default_val[3] = 1;
  3453. } else if(dz->mode == FOF_LOHI) {
  3454. ap->lo[3] = 0;
  3455. ap->hi[3] = 32167;
  3456. ap->default_val[3] = 0;
  3457. ap->lo[4] = 0;
  3458. ap->hi[4] = 32167;
  3459. ap->default_val[4] = 0;
  3460. ap->lo[5] = 55;
  3461. ap->hi[5] = 880;
  3462. ap->default_val[5] = 55;
  3463. ap->lo[6] = 55;
  3464. ap->hi[6] = 880;
  3465. ap->default_val[6] = 880;
  3466. } else if(dz->mode == FOF_TRIPLE) {
  3467. ap->lo[3] = 0;
  3468. ap->hi[3] = 32167;
  3469. ap->default_val[3] = 0;
  3470. ap->lo[4] = 0;
  3471. ap->hi[4] = 32167;
  3472. ap->default_val[4] = 0;
  3473. ap->lo[5] = 0;
  3474. ap->hi[5] = 32167;
  3475. ap->default_val[5] = 0;
  3476. ap->lo[6] = 55;
  3477. ap->hi[6] = 880;
  3478. ap->default_val[6] = 55;
  3479. ap->lo[7] = 55;
  3480. ap->hi[7] = 880;
  3481. ap->default_val[7] = 880;
  3482. ap->lo[8] = 0;
  3483. ap->hi[8] = 1;
  3484. ap->default_val[8] = 0;
  3485. ap->lo[9] = 0;
  3486. ap->hi[9] = 1;
  3487. ap->default_val[9] = 1;
  3488. }
  3489. dz->maxmode = 8;
  3490. break;
  3491. }
  3492. if(!sloom)
  3493. put_default_vals_in_all_params(dz);
  3494. return(FINISHED);
  3495. }
  3496. /************************ HANDLE_THE_SPECIAL_DATA *********************/
  3497. int handle_the_special_data(int *cmdlinecnt,char ***cmdline,dataptr dz)
  3498. {
  3499. int exit_status;
  3500. aplptr ap = dz->application;
  3501. if(ap->special_data) {
  3502. if(!sloom) {
  3503. if(*cmdlinecnt <= 0) {
  3504. sprintf(errstr,"Insufficient parameters on command line.\n");
  3505. return(USAGE_ONLY);
  3506. }
  3507. }
  3508. if((exit_status = setup_the_special_data_ranges
  3509. (dz->mode,dz->infile->srate,dz->duration,dz->nyquist,dz->wlength,dz->infile->channels,ap))<0)
  3510. return(exit_status);
  3511. if((exit_status = read_special_data((*cmdline)[0],dz))<0)
  3512. return(exit_status);
  3513. (*cmdline)++;
  3514. (*cmdlinecnt)--;
  3515. }
  3516. return(FINISHED);
  3517. }
  3518. /************************ SETUP_SPECIAL_DATA_RANGES *********************/
  3519. int setup_the_special_data_ranges(int mode,int srate,double duration,double nyquist,int wlength,int channels,aplptr ap)
  3520. {
  3521. switch(ap->special_data) {
  3522. case(FOFEX_EXCLUDES):
  3523. ap->min_special = 0;
  3524. ap->max_special = round(duration * srate);
  3525. break;
  3526. case(FOFBANK_INFO):
  3527. ap->min_special = 1;
  3528. ap->max_special = round(duration * 4000); // 4000 guestimate of highest poss fof frq
  3529. ap->min_special2 = srate/4000;
  3530. ap->max_special2 = ceil(srate/MINPITCH);
  3531. break;
  3532. default:
  3533. sprintf(errstr,"Unknown special_data type: setup_the_special_data_ranges()\n");
  3534. return(PROGRAM_ERROR);
  3535. }
  3536. return(FINISHED);
  3537. }
  3538. /************************* READ_SPECIAL_DATA *******************/
  3539. int read_special_data(char *str,dataptr dz)
  3540. {
  3541. aplptr ap = dz->application;
  3542. switch(ap->special_data) {
  3543. case(FOFEX_EXCLUDES): return get_fofex_exclude_data(str,dz);
  3544. case(FOFBANK_INFO): return get_fofbank_info(str,dz);
  3545. }
  3546. return(FINISHED);
  3547. }
  3548. /************************* SMOOTH_OCT_GLITCHES *******************/
  3549. #define MINSPEECHGLITCH (0.15) // Assume minimum time for speaking voice to leap > 8va and back is > 150 mS
  3550. void smooth_oct_glitches(dataptr dz)
  3551. {
  3552. int n, m, jumpcnt, start, end, k, datalen, endtime_index, jump[2];
  3553. int octglitch;
  3554. double interval, *pitchdata = dz->brk[0], time[2];
  3555. datalen = dz->brksize[0] * 2;
  3556. endtime_index = datalen - 2;
  3557. jumpcnt = 0;
  3558. m = 1;
  3559. n = 3;
  3560. while(n < datalen) {
  3561. interval = pitchdata[n]/pitchdata[m];
  3562. if(interval > 2.0) {
  3563. jump[jumpcnt] = n;
  3564. time[jumpcnt] = pitchdata[n-1];
  3565. jumpcnt++;
  3566. }
  3567. else if(interval < 0.5) {
  3568. jump[jumpcnt] = -n;
  3569. time[jumpcnt] = pitchdata[n-1];
  3570. jumpcnt++;
  3571. }
  3572. if(jumpcnt == 2) {
  3573. octglitch = 0;
  3574. if((jump[0] < 0) && (jump[1] > 0)) {
  3575. octglitch = -1;
  3576. } else if((jump[0] > 0) && (jump[1] < 0) ) {
  3577. octglitch = 1;
  3578. }
  3579. if(octglitch && (time[1] - time[0] < MINSPEECHGLITCH)) {
  3580. start = (int)abs(jump[0]);
  3581. end = (int)abs(jump[1]);
  3582. k = start;
  3583. if(octglitch > 0) {
  3584. while(k < end) {
  3585. pitchdata[k] /= 2.0;
  3586. k += 2;
  3587. }
  3588. } else {
  3589. while(k < end) {
  3590. pitchdata[k] *= 2.0;
  3591. k += 2;
  3592. }
  3593. }
  3594. jumpcnt = 0;
  3595. } else {
  3596. jump[0] = jump[1];
  3597. time[0] = time[1];
  3598. jumpcnt = 1;
  3599. }
  3600. }
  3601. n += 2;
  3602. m += 2;
  3603. }
  3604. if(jumpcnt) {
  3605. if(time[0] < MINSPEECHGLITCH) { // SINGLE LEAP AT START
  3606. k = 1;
  3607. end = (int)abs(jump[0]);
  3608. if(jump[0] > 0) {
  3609. while(k < end) {
  3610. pitchdata[k] *= 2.0;
  3611. k += 2;
  3612. }
  3613. } else {
  3614. while(k < end) {
  3615. pitchdata[k] /= 2.0;
  3616. k += 2;
  3617. }
  3618. }
  3619. } else if(pitchdata[endtime_index] - time[0] < MINSPEECHGLITCH) { // SINGLE LEAP LEFT AT END
  3620. k = (int)abs(jump[0]);
  3621. end = datalen;
  3622. if(jump[0] > 0) {
  3623. while(k < end) {
  3624. pitchdata[k] /= 2.0;
  3625. k += 2;
  3626. }
  3627. } else {
  3628. while(k < end) {
  3629. pitchdata[k] *= 2.0;
  3630. k += 2;
  3631. }
  3632. }
  3633. }
  3634. }
  3635. }
  3636. /********************************************* ESTABLISH_NORMALISERS **********************************/
  3637. int establish_normalisers(int unitlen, dataptr dz)
  3638. {
  3639. int exit_status;
  3640. float *ibuf;
  3641. double *norm, maxsamp;
  3642. int fofstart, fofend, ipos, k;
  3643. int normlen;
  3644. normlen = (dz->insams[0]/unitlen);
  3645. fofstart = unitlen;
  3646. ibuf = dz->sampbuf[0];
  3647. if((dz->parray[0] = (double *)malloc(normlen * sizeof(double)))==NULL) {
  3648. sprintf(errstr,"INSUFFICIENT MEMORY FOR NORMALISERS.\n");
  3649. return(MEMORY_ERROR);
  3650. }
  3651. norm = dz->parray[0];
  3652. k = 1;
  3653. while(fofstart < dz->insams[0]) {
  3654. ipos = fofstart % dz->buflen;
  3655. fofend = ipos + unitlen;
  3656. maxsamp = 0.0;
  3657. while(ipos < fofend) {
  3658. maxsamp = max(maxsamp,fabs(ibuf[ipos]));
  3659. if(++ipos >= dz->ssampsread) {
  3660. if((exit_status = read_samps(ibuf,dz))<0)
  3661. return(exit_status);
  3662. ipos = 0;
  3663. fofend -= dz->buflen;
  3664. }
  3665. }
  3666. norm[k++] = FOF_NORM_LEVEL/maxsamp;
  3667. fofstart += unitlen;
  3668. }
  3669. return FINISHED;
  3670. }
  3671. /****************************** GET_MODE *********************************/
  3672. int get_the_mode_from_cmdline(char *str,dataptr dz)
  3673. {
  3674. char temp[200], *p;
  3675. if(sscanf(str,"%s",temp)!=1) {
  3676. sprintf(errstr,"Cannot read mode of program.\n");
  3677. return(USAGE_ONLY);
  3678. }
  3679. p = temp + strlen(temp) - 1;
  3680. while(p >= temp) {
  3681. if(!isdigit(*p)) {
  3682. fprintf(stderr,"Invalid mode of program entered.\n");
  3683. return(USAGE_ONLY);
  3684. }
  3685. p--;
  3686. }
  3687. if(sscanf(str,"%d",&dz->mode)!=1) {
  3688. fprintf(stderr,"Cannot read mode of program.\n");
  3689. return(USAGE_ONLY);
  3690. }
  3691. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  3692. fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  3693. return(USAGE_ONLY);
  3694. }
  3695. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  3696. return(FINISHED);
  3697. }
  3698. /****************************** REMOVE_ZERO_SIGNAL_AREAS *********************************/
  3699. int remove_zero_signal_areas(int *outsegs,int *outcnt,dataptr dz)
  3700. {
  3701. double *frqdata = dz->brk[0];
  3702. int n, segcnt = 0;
  3703. int zeropnt[2]={0}, zerocnt = 0, brklen = dz->brksize[0] * 2, frqindx, timindx, nufrqindx, nutimindx, top, bottom;
  3704. n = 0;
  3705. timindx = 0;
  3706. frqindx = 1;
  3707. while (n < dz->brksize[0]) {
  3708. zerocnt = 0;
  3709. if(frqdata[frqindx] < 0.0) {
  3710. zeropnt[0] = (int)round(frqdata[timindx] * (double)dz->infile->srate);
  3711. zerocnt = 1;
  3712. nufrqindx =frqindx + 2;
  3713. nutimindx =timindx + 2;
  3714. while(nufrqindx < brklen) {
  3715. if(frqdata[nufrqindx] < 0.0) {
  3716. zeropnt[1] = (int)round(frqdata[nutimindx] * (double)dz->infile->srate);
  3717. zerocnt = 2;
  3718. frqindx = nufrqindx;
  3719. timindx = nutimindx;
  3720. n++;
  3721. nufrqindx += 2;
  3722. nutimindx += 2;
  3723. } else {
  3724. break;
  3725. }
  3726. }
  3727. while(outsegs[segcnt] < zeropnt[0]) {
  3728. if(++segcnt >= *outcnt)
  3729. return FINISHED;
  3730. }
  3731. segcnt--;
  3732. bottom = segcnt;
  3733. top = segcnt + 2;
  3734. if(top >= *outcnt) { // REMOVE LAST SEGMENT: DOES LOWERING outcnt WORK ?????
  3735. *outcnt -= 2;
  3736. return FINISHED;
  3737. }
  3738. while(top < *outcnt) { // ELIMINATE SEGMENT CONTANING ZERO PITCH POINT
  3739. outsegs[bottom] = outsegs[top];
  3740. outsegs[bottom+1] = outsegs[top+1];
  3741. bottom+=2;
  3742. top+=2;
  3743. }
  3744. *outcnt -= 2;
  3745. if (zerocnt > 1) {
  3746. while(outsegs[segcnt] < zeropnt[1]) {
  3747. top = segcnt + 2;
  3748. bottom = segcnt;
  3749. if(top >= *outcnt) { // REMOVE LAST SEGMENT: DOES LOWERING outcnt WORK ?????
  3750. *outcnt -= 2;
  3751. return FINISHED;
  3752. }
  3753. while(top < *outcnt) { // ELIMINATE SEGMENT CONTANING ZERO PITCH POINT
  3754. outsegs[bottom] = outsegs[top];
  3755. outsegs[bottom+1] = outsegs[top+1];
  3756. bottom+=2;
  3757. top+=2;
  3758. }
  3759. *outcnt -= 2;
  3760. }
  3761. }
  3762. }
  3763. n++;
  3764. timindx += 2;
  3765. frqindx += 2;
  3766. }
  3767. return(FINISHED);
  3768. }
  3769. /****************************** REMOVE_OUTOFRANGE_FOFS *********************************/
  3770. int remove_outofrange_fofs(int *outsegs,int *outcnt,dataptr dz)
  3771. {
  3772. int n,m,j,k,dur;
  3773. int lolim = (int)round((double)dz->infile->srate/2500.0); /* 40 - 2500 Hz extremal limits of range of sung voice */
  3774. int hilim = (int)round((double)dz->infile->srate/40.0);
  3775. n = 0;
  3776. m = 1;
  3777. while(n < *outcnt) {
  3778. dur = outsegs[m] - outsegs[n];
  3779. if((dur < lolim) || (dur > hilim)) {
  3780. j = n;
  3781. k = n+2;
  3782. if(k >= *outcnt) {
  3783. *outcnt -= 2;
  3784. return FINISHED;
  3785. }
  3786. while(k < *outcnt)
  3787. outsegs[j++] = outsegs[k++];
  3788. *outcnt -= 2;
  3789. } else {
  3790. n += 2;
  3791. m += 2;
  3792. }
  3793. }
  3794. return(FINISHED);
  3795. }
  3796. /****************************** REMOVE_LOLEVEL_FOFS *********************************/
  3797. int remove_lolevel_fofs(int *outsegs,int *outcnt,dataptr dz)
  3798. {
  3799. int exit_status;
  3800. int n,m,j,k,totalsamps = 0, endsegindx, levelcnt, ipos, levelsiz = (*outcnt)/2;
  3801. double maxsamp = 0.0, maxlocalsamp = 0.0, *level, lolim;
  3802. float *ibuf = dz->sampbuf[0];
  3803. if((level = (double *)malloc(levelsiz * sizeof(double))) == NULL) {
  3804. sprintf(errstr,"INSUFFICIENT MEMORY establishing level check array.\n");
  3805. return(MEMORY_ERROR);
  3806. }
  3807. if((sndseekEx(dz->ifd[0],0,0)<0)){
  3808. sprintf(errstr,"sndseek() failed\n");
  3809. return SYSTEM_ERROR;
  3810. }
  3811. dz->total_samps_read = 0;
  3812. if((exit_status = read_samps(ibuf,dz))<0)
  3813. return(exit_status);
  3814. endsegindx = 1;
  3815. levelcnt = 0;
  3816. while(dz->ssampsread > 0) {
  3817. ipos = 0;
  3818. while(ipos < dz->ssampsread) {
  3819. maxsamp = max(maxsamp,fabs(ibuf[ipos]));
  3820. maxlocalsamp = max(maxlocalsamp,fabs(ibuf[ipos]));
  3821. ipos++;
  3822. totalsamps++;
  3823. if(totalsamps >= outsegs[endsegindx]) {
  3824. if(levelcnt < levelsiz) {
  3825. level[levelcnt++] = maxlocalsamp;
  3826. maxlocalsamp = 0.0;
  3827. endsegindx += 2;
  3828. }
  3829. }
  3830. }
  3831. if((exit_status = read_samps(ibuf,dz))<0)
  3832. return(exit_status);
  3833. }
  3834. if((sndseekEx(dz->ifd[0],0,0)<0)){
  3835. sprintf(errstr,"sndseek() failed\n");
  3836. return SYSTEM_ERROR;
  3837. }
  3838. dz->total_samps_read = 0;
  3839. if((exit_status = read_samps(ibuf,dz))<0)
  3840. return(exit_status);
  3841. lolim = maxsamp * dbtogain(dz->param[1]);
  3842. n = 0;
  3843. m = 0;
  3844. while(n < *outcnt) {
  3845. if(level[m] < lolim) {
  3846. j = n;
  3847. k = n+2;
  3848. if(k >= *outcnt) {
  3849. *outcnt -= 2;
  3850. return FINISHED;
  3851. }
  3852. while(k < *outcnt)
  3853. outsegs[j++] = outsegs[k++];
  3854. *outcnt -= 2;
  3855. j = m;
  3856. k = m+1;
  3857. while(k < levelcnt)
  3858. level[j++] = level[k++];
  3859. levelcnt--;
  3860. } else {
  3861. n += 2;
  3862. m++;
  3863. }
  3864. }
  3865. return(FINISHED);
  3866. }
  3867. /*************************** CREATE_FOFEX_SNDBUFS **************************/
  3868. int create_fofex_sndbufs(dataptr dz)
  3869. {
  3870. int n;
  3871. size_t bigbufsize;
  3872. if(dz->sbufptr == 0 || dz->sampbuf==0) {
  3873. sprintf(errstr,"buffer pointers not allocated: create_fofex_sndbufs()\n");
  3874. return(PROGRAM_ERROR);
  3875. }
  3876. bigbufsize = (size_t) Malloc(-1);
  3877. bigbufsize /= dz->bufcnt;
  3878. if(bigbufsize <=0) {
  3879. bigbufsize = (size_t)( F_SECSIZE * sizeof(float)); /* RWD keep ths for now */
  3880. }
  3881. dz->buflen = (int)(bigbufsize / sizeof(float));
  3882. if(dz->buflen <= dz->descriptor_samps)
  3883. dz->buflen = dz->descriptor_samps + 1;
  3884. /*RWD also cover n-channels usage */
  3885. dz->buflen = (dz->buflen / dz->infile->channels) * dz->infile->channels;
  3886. bigbufsize = (size_t)(dz->buflen * sizeof(float));
  3887. if((dz->bigbuf = (float *)malloc(bigbufsize * dz->bufcnt)) == NULL) {
  3888. sprintf(errstr,"INSUFFICIENT MEMORY to create sound buffers.\n");
  3889. return(PROGRAM_ERROR);
  3890. }
  3891. for(n=0;n<dz->bufcnt;n++)
  3892. dz->sbufptr[n] = dz->sampbuf[n] = dz->bigbuf + (int)(dz->buflen * n);
  3893. dz->sampbuf[n] = dz->bigbuf + (int)(dz->buflen * n);
  3894. return(FINISHED);
  3895. }
  3896. #ifndef round
  3897. int round(double a)
  3898. {
  3899. return (int)floor(a+0.5);
  3900. }
  3901. #endif