specanal.c 156 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165
  1. /*
  2. * Copyright (c) 1983-2013 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. #include <stdio.h>
  21. #include <stdlib.h>
  22. #include <structures.h>
  23. #include <tkglobals.h>
  24. #include <pnames.h>
  25. #include <filetype.h>
  26. #include <processno.h>
  27. #include <modeno.h>
  28. #include <logic.h>
  29. #include <globcon.h>
  30. #include <cdpmain.h>
  31. #include <math.h>
  32. #include <mixxcon.h>
  33. #include <osbind.h>
  34. #include <science.h>
  35. #include <ctype.h>
  36. #include <sfsys.h>
  37. #include <string.h>
  38. #include <srates.h>
  39. #include <formants.h>
  40. #include <speccon.h>
  41. #define SAFETY 4
  42. #define SA_CHANS (0)
  43. #define SA_WINOVLP (1)
  44. #define SA_FORMANT_BANDS (2)
  45. #define SA_PICH_LOLM (2) /* low limit of frq search */
  46. #define SA_PICH_HILM (3) /* high limit of frq search */
  47. #define SA_PICH_RNGE (4) /* semitone range for frqs to be in tune with expected frq (semitones) */
  48. #define SA_PICH_SRATIO (5) /* sig-to-noise ratio: below this, window assumed to be (pitchless) noise */
  49. #define SA_PICH_MATCH (6) /* how many of (MAXIMI=) 8 loudest peaks must be partials */
  50. #define SA_PICH_VALID (7) /* how many successive windows need to be pitched to confirm true pitch */
  51. #define SA_PKCNT (2) /* Number of peaks to use in filter design */
  52. #define SA_TSTEP (3) /* Time-step between pitch-assessments: mS */
  53. #define SA_BOTRANGE (4) /* Lowest acceptable pitch (MIDI) */
  54. #define SA_TOPRANGE (5) /* Highest acceptable pitch (MIDI) */
  55. #define SA_GATE (6) /* Level, relative to maxlevel, at which signal assumed to be silence */
  56. #define SA_MIN_SMOOTH_SET (3) /* minimum number of adjacent windows to be pitched, when smoothing */
  57. #define PEAK_LIMIT (.05)
  58. #define MAX_GLISRATE (16.0) /* Assumptions: pitch can't move faster than 16 octaves per sec: MAX_GLISRATE */
  59. /* Possible movement from window-to-window = MAX_GLISRATE * dz->frametime */
  60. #define LAST_SMOOTH_NOT_SET (-1)
  61. #define EIGHT_OVER_SEVEN (1.142857143)
  62. #define MAXIMUM_PARTIAL (64)
  63. #define ALMOST_TWO (1.75)
  64. // Pitch-absent markers
  65. // NOT_SOUND = -2
  66. // NOT_PITCH = -1
  67. #define SA_TRANSIT 0.05 // Transition time when stepping from one pitch to another
  68. #define SA_PVOC_TEST (0)
  69. #define SA_FFT (1)
  70. #define SA_PVOC (2)
  71. #define SA_LOGFFT (3)
  72. #define SA_CEPSTRUM (4)
  73. #define SA_FORMANTS (5)
  74. #define SA_AVERAGE (6)
  75. #define SA_FILTER (7)
  76. #define SA_TEMPERED (8)
  77. #define SA_HFVARY (9)
  78. #define SA_IGNORE_AMP (0)
  79. #define SA_NO_HARMONICS (1)
  80. #define SA_MIDILIST (2)
  81. #define SA_DECHROM (3)
  82. #define SA_DDOWNOCT (4)
  83. #define SA_DDOWN2OCT (5)
  84. #define SA_DOWNOCT (0)
  85. #define SA_DOWN2OCT (1)
  86. #define CHAN_SRCHRANGE_F (4)
  87. #define BINCNT (128) /* Number of semitone bins */
  88. #define envcnt rampbrksize
  89. #define framecnt ringsize
  90. #define pitchcnt temp_sampsize
  91. static double quartertone;
  92. #ifdef unix
  93. #define round(x) lround((x))
  94. #endif
  95. #ifndef HUGE
  96. #define HUGE 3.40282347e+38F
  97. #endif
  98. char errstr[2400];
  99. int anal_infiles = 1;
  100. int sloom = 0;
  101. int sloombatch = 0;
  102. const char* cdp_version = "6.2.0";
  103. //CDP LIB REPLACEMENTS
  104. static int check_specanal_param_validity_and_consistency(dataptr dz);
  105. static int setup_specanal_application(dataptr dz);
  106. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  107. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  108. static int setup_specanal_param_ranges_and_defaults(dataptr dz);
  109. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
  110. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  111. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  112. static int establish_application(dataptr dz);
  113. static int initialise_vflags(dataptr dz);
  114. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  115. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  116. static int mark_parameter_types(dataptr dz,aplptr ap);
  117. static int assign_file_data_storage(int infilecnt,dataptr dz);
  118. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  119. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  120. static int get_the_mode_from_cmdline(char *str,dataptr dz);
  121. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  122. static int specanal(dataptr dz);
  123. static void hamming(float *win,int winLen,int even);
  124. static int pvoc_float_array(int nnn,float **ptr);
  125. static int sndwrite_header(int N2,int *Nchans,float *arate,float R,int D,int origsize,int *isr,int M,dataptr dz);
  126. static int write_samps_pvoc(float *bbuf,int samps_to_write,dataptr dz);
  127. static int fft_(float *a, float *b, int nseg, int n, int nspn, int isn,float *at,float *ck,float *bt,float *sk,int *np);
  128. static int fftmx(float *a,float *b,int ntot,int n,int nspan,int isn,int m,int *kt,float *at,float *ck,float *bt,float *sk,int *np,int nfac[]);
  129. static int reals_(float *a, float *b, int n, int isn);
  130. static int sa_initialise_specenv(dataptr dz);
  131. static int sa_set_specenv_frqs(dataptr dz);
  132. static int sa_setup_octaveband_steps(double **interval,dataptr dz);
  133. static int sa_setup_low_octave_bands(int arraycnt,dataptr dz);
  134. static int sa_extract_specenv(float *anal,dataptr dz);
  135. static int is_a_harmonic_x(double frq1,double frq2);
  136. static int extract_env_from_sndfile(dataptr dz);
  137. static int get_tempered_pitch(float *averages, float *averages2, float *averages3, dataptr dz);
  138. static int smooth_and_output_tempered_pitch(dataptr dz);
  139. static int check_specanal_param_validity_and_consistency2(dataptr dz);
  140. static int get_tempered_hf(float *averages, float *averages2, float *averages3, dataptr dz);
  141. static int smooth_and_output_varying_hf(dataptr dz);
  142. static int rerange_outofrange_pitch(int strandindex,int eventindex,dataptr dz);
  143. /**************************************** MAIN *********************************************/
  144. int main(int argc,char *argv[])
  145. {
  146. int exit_status;
  147. dataptr dz = NULL;
  148. char **cmdline;
  149. int cmdlinecnt;
  150. aplptr ap;
  151. int is_launched = FALSE;
  152. quartertone = sqrt(SEMITONE_INTERVAL);
  153. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  154. fprintf(stdout,"%s\n",cdp_version);
  155. fflush(stdout);
  156. return 0;
  157. }
  158. /* CHECK FOR SOUNDLOOM */
  159. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  160. sloom = 0;
  161. sloombatch = 1;
  162. }
  163. if(sflinit("cdp")){
  164. sfperror("cdp: initialisation\n");
  165. return(FAILED);
  166. }
  167. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  168. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  169. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  170. return(FAILED);
  171. }
  172. if(!sloom) {
  173. if(argc == 1) {
  174. usage1();
  175. return(FAILED);
  176. } else if(argc == 2) {
  177. usage2(argv[1]);
  178. return(FAILED);
  179. }
  180. }
  181. if(!sloom) {
  182. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  183. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  184. return(FAILED);
  185. }
  186. cmdline = argv;
  187. cmdlinecnt = argc;
  188. if((get_the_process_no(argv[0],dz))<0)
  189. return(FAILED);
  190. cmdline++;
  191. cmdlinecnt--;
  192. dz->maxmode = 10;
  193. if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
  194. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  195. return(exit_status);
  196. }
  197. cmdline++;
  198. cmdlinecnt--;
  199. // setup_particular_application =
  200. if((exit_status = setup_specanal_application(dz))<0) {
  201. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  202. return(FAILED);
  203. }
  204. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  205. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  206. return(FAILED);
  207. }
  208. } else {
  209. //parse_TK_data() =
  210. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  211. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  212. return(exit_status);
  213. }
  214. }
  215. ap = dz->application;
  216. // parse_infile_and_hone_type() =
  217. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  218. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  219. return(FAILED);
  220. }
  221. // open_first_infile CDP LIB
  222. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  223. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  224. return(FAILED);
  225. }
  226. cmdlinecnt--;
  227. cmdline++;
  228. // setup_param_ranges_and_defaults() =
  229. if((exit_status = setup_specanal_param_ranges_and_defaults(dz))<0) {
  230. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  231. return(FAILED);
  232. }
  233. // handle_extra_infiles() : redundant
  234. // handle_outfile() =
  235. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
  236. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  237. return(FAILED);
  238. }
  239. // handle_formants() redundant
  240. // handle_formant_quiksearch() redundant
  241. // handle_special_data() redundant
  242. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  243. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  244. return(FAILED);
  245. }
  246. // check_param_validity_and_consistency....
  247. if((exit_status = check_specanal_param_validity_and_consistency(dz))<0) {
  248. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  249. return(FAILED);
  250. }
  251. is_launched = TRUE;
  252. if((exit_status = specanal(dz))<0) {
  253. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  254. return(FAILED);
  255. }
  256. switch(dz->mode) {
  257. case(SA_PVOC_TEST):
  258. dz->process = PVOC_ANAL;
  259. if((exit_status = complete_output(dz))<0) {
  260. dz->process = SPECANAL;
  261. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  262. return(FAILED);
  263. }
  264. dz->process = SPECANAL;
  265. break;
  266. default:
  267. if((exit_status = complete_output(dz))<0) {
  268. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  269. return(FAILED);
  270. }
  271. break;
  272. }
  273. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz);
  274. free(dz);
  275. return(SUCCEEDED);
  276. }
  277. /**********************************************
  278. REPLACED CDP LIB FUNCTIONS
  279. **********************************************/
  280. /****************************** SET_PARAM_DATA *********************************/
  281. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  282. {
  283. ap->special_data = (char)special_data;
  284. ap->param_cnt = (char)paramcnt;
  285. ap->max_param_cnt = (char)maxparamcnt;
  286. if(ap->max_param_cnt>0) {
  287. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  288. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  289. return(MEMORY_ERROR);
  290. }
  291. strcpy(ap->param_list,paramlist);
  292. }
  293. return(FINISHED);
  294. }
  295. /****************************** SET_VFLGS *********************************/
  296. int set_vflgs
  297. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  298. {
  299. ap->option_cnt = (char) optcnt; /*RWD added cast */
  300. if(optcnt) {
  301. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  302. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  303. return(MEMORY_ERROR);
  304. }
  305. strcpy(ap->option_list,optlist);
  306. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  307. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  308. return(MEMORY_ERROR);
  309. }
  310. strcpy(ap->option_flags,optflags);
  311. }
  312. ap->vflag_cnt = (char) vflagcnt;
  313. ap->variant_param_cnt = (char) vparamcnt;
  314. if(vflagcnt) {
  315. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  316. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  317. return(MEMORY_ERROR);
  318. }
  319. strcpy(ap->variant_list,varlist);
  320. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  321. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  322. return(MEMORY_ERROR);
  323. }
  324. strcpy(ap->variant_flags,varflags);
  325. }
  326. return(FINISHED);
  327. }
  328. /***************************** APPLICATION_INIT **************************/
  329. int application_init(dataptr dz)
  330. {
  331. int exit_status;
  332. int storage_cnt;
  333. int tipc, brkcnt;
  334. aplptr ap = dz->application;
  335. if(ap->vflag_cnt>0)
  336. initialise_vflags(dz);
  337. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  338. ap->total_input_param_cnt = (char)tipc;
  339. if(tipc>0) {
  340. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  341. return(exit_status);
  342. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  343. return(exit_status);
  344. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  345. return(exit_status);
  346. }
  347. brkcnt = tipc;
  348. //THERE ARE NO INPUTFILE brktables USED IN THIS PROCESS
  349. if(brkcnt>0) {
  350. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  351. return(exit_status);
  352. }
  353. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  354. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  355. return(exit_status);
  356. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  357. return(exit_status);
  358. }
  359. if((exit_status = mark_parameter_types(dz,ap))<0)
  360. return(exit_status);
  361. // establish_infile_constants() replaced by
  362. dz->infilecnt = 1;
  363. //establish_bufptrs_and_extra_buffers():
  364. return(FINISHED);
  365. }
  366. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  367. /* RWD mallo changed to calloc; helps debug verison run as release! */
  368. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  369. {
  370. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  371. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  372. return(MEMORY_ERROR);
  373. }
  374. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  375. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  376. return(MEMORY_ERROR);
  377. }
  378. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  379. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  380. return(MEMORY_ERROR);
  381. }
  382. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  383. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  384. return(MEMORY_ERROR);
  385. }
  386. return(FINISHED);
  387. }
  388. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  389. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  390. {
  391. int n;
  392. for(n=0;n<storage_cnt;n++) {
  393. dz->is_int[n] = (char)0;
  394. dz->no_brk[n] = (char)0;
  395. }
  396. return(FINISHED);
  397. }
  398. /***************************** MARK_PARAMETER_TYPES **************************/
  399. int mark_parameter_types(dataptr dz,aplptr ap)
  400. {
  401. int n, m; /* PARAMS */
  402. for(n=0;n<ap->max_param_cnt;n++) {
  403. switch(ap->param_list[n]) {
  404. case('0'): break; /* dz->is_active[n] = 0 is default */
  405. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  406. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  407. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  408. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  409. default:
  410. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  411. return(PROGRAM_ERROR);
  412. }
  413. } /* OPTIONS */
  414. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  415. switch(ap->option_list[n]) {
  416. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  417. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  418. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  419. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  420. default:
  421. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  422. return(PROGRAM_ERROR);
  423. }
  424. } /* VARIANTS */
  425. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  426. switch(ap->variant_list[n]) {
  427. case('0'): break;
  428. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  429. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  430. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  431. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  432. default:
  433. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  434. return(PROGRAM_ERROR);
  435. }
  436. } /* INTERNAL */
  437. for(n=0,
  438. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  439. switch(ap->internal_param_list[n]) {
  440. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  441. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  442. case('d'): dz->no_brk[m] = (char)1; break;
  443. default:
  444. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  445. return(PROGRAM_ERROR);
  446. }
  447. }
  448. return(FINISHED);
  449. }
  450. /************************ HANDLE_THE_OUTFILE *********************/
  451. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
  452. {
  453. char *filename = (*cmdline)[0];
  454. if(filename[0]=='-' && filename[1]=='f') {
  455. dz->floatsam_output = 1;
  456. dz->true_outfile_stype = SAMP_FLOAT;
  457. filename+= 2;
  458. }
  459. if(!sloom) {
  460. if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
  461. sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
  462. return(DATA_ERROR);
  463. }
  464. }
  465. strcpy(dz->outfilename,filename);
  466. (*cmdline)++;
  467. (*cmdlinecnt)--;
  468. return(FINISHED);
  469. }
  470. /***************************** ESTABLISH_APPLICATION **************************/
  471. int establish_application(dataptr dz)
  472. {
  473. aplptr ap;
  474. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  475. sprintf(errstr,"establish_application()\n");
  476. return(MEMORY_ERROR);
  477. }
  478. ap = dz->application;
  479. memset((char *)ap,0,sizeof(struct applic));
  480. return(FINISHED);
  481. }
  482. /************************* INITIALISE_VFLAGS *************************/
  483. int initialise_vflags(dataptr dz)
  484. {
  485. int n;
  486. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  487. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  488. return(MEMORY_ERROR);
  489. }
  490. for(n=0;n<dz->application->vflag_cnt;n++)
  491. dz->vflag[n] = FALSE;
  492. return FINISHED;
  493. }
  494. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  495. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  496. {
  497. int n;
  498. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  499. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  500. return(MEMORY_ERROR);
  501. }
  502. for(n=0;n<tipc;n++)
  503. ap->default_val[n] = 0.0;
  504. return(FINISHED);
  505. }
  506. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  507. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  508. {
  509. int n;
  510. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  511. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  512. return(MEMORY_ERROR);
  513. }
  514. for(n=0;n<tipc;n++)
  515. dz->is_active[n] = (char)0;
  516. return(FINISHED);
  517. }
  518. /************************* SETUP_SPECANAL_APPLICATION *******************/
  519. int setup_specanal_application(dataptr dz)
  520. {
  521. int exit_status;
  522. aplptr ap;
  523. if((exit_status = establish_application(dz))<0) // GLOBAL
  524. return(FAILED);
  525. ap = dz->application;
  526. // SEE parstruct FOR EXPLANATION of next 2 functions
  527. if(dz->mode == SA_FORMANTS) {
  528. if((exit_status = set_param_data(ap,0 ,3,3,"iii"))<0)
  529. return(FAILED);
  530. } else if(dz->mode == SA_FILTER) {
  531. if((exit_status = set_param_data(ap,0 ,4,3,"iii0"))<0)
  532. return(FAILED);
  533. } else if(dz->mode == SA_TEMPERED) {
  534. if((exit_status = set_param_data(ap,0 ,4,3,"ii0d"))<0)
  535. return(FAILED);
  536. } else if(dz->mode == SA_HFVARY) {
  537. if((exit_status = set_param_data(ap,0 ,4,4,"iiid"))<0)
  538. return(FAILED);
  539. } else {
  540. if((exit_status = set_param_data(ap,0 ,2,2,"ii"))<0)
  541. return(FAILED);
  542. }
  543. // set_legal_infile_structure -->
  544. dz->has_otherfile = FALSE;
  545. // assign_process_logic -->
  546. dz->input_data_type = SNDFILES_ONLY;
  547. switch(dz->mode) {
  548. case(SA_FFT):
  549. case(SA_LOGFFT):
  550. case(SA_CEPSTRUM):
  551. case(SA_FORMANTS):
  552. if((exit_status = set_vflgs(ap,"",0,"","n",1,0,"0"))<0)
  553. return(FAILED);
  554. dz->process_type = TO_TEXTFILE;
  555. dz->outfiletype = TEXTFILE_OUT;
  556. break;
  557. case(SA_PVOC):
  558. if((exit_status = set_vflgs(ap,"",0,"","nf",2,0,"00"))<0)
  559. return(FAILED);
  560. dz->process_type = TO_TEXTFILE;
  561. dz->outfiletype = TEXTFILE_OUT;
  562. break;
  563. case(SA_AVERAGE):
  564. if((exit_status = set_vflgs(ap,"",0,"","0",0,0,""))<0)
  565. return(FAILED);
  566. dz->process_type = TO_TEXTFILE;
  567. dz->outfiletype = TEXTFILE_OUT;
  568. break;
  569. case(SA_FILTER):
  570. if((exit_status = set_vflgs(ap,"",0,"","ahmcdD",6,0,"000000"))<0)
  571. return(FAILED);
  572. dz->process_type = TO_TEXTFILE;
  573. dz->outfiletype = TEXTFILE_OUT;
  574. break;
  575. case(SA_TEMPERED):
  576. if((exit_status = set_vflgs(ap,"btg",3,"iid","",0,0,""))<0)
  577. return(FAILED);
  578. dz->process_type = TO_TEXTFILE;
  579. dz->outfiletype = TEXTFILE_OUT;
  580. break;
  581. case(SA_HFVARY):
  582. if((exit_status = set_vflgs(ap,"btg",3,"iid","d",2,0,"00"))<0)
  583. return(FAILED);
  584. dz->process_type = TO_TEXTFILE;
  585. dz->outfiletype = TEXTFILE_OUT;
  586. break;
  587. default:
  588. if((exit_status = set_vflgs(ap,"",0,"","",0,0,""))<0)
  589. return(FAILED);
  590. dz->process_type = BIG_ANALFILE;
  591. dz->outfiletype = ANALFILE_OUT;
  592. }
  593. return application_init(dz); //GLOBAL
  594. }
  595. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  596. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  597. {
  598. int exit_status;
  599. infileptr infile_info;
  600. if(!sloom) {
  601. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  602. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  603. return(MEMORY_ERROR);
  604. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  605. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  606. return(DATA_ERROR);
  607. } else if(infile_info->filetype != SNDFILE) {
  608. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  609. return(DATA_ERROR);
  610. } else if(infile_info->channels != 1) {
  611. sprintf(errstr,"File %s is not of correct type (must be mono)\n",cmdline[0]);
  612. return(DATA_ERROR);
  613. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  614. sprintf(errstr,"Failed to copy file parsing information\n");
  615. return(PROGRAM_ERROR);
  616. }
  617. free(infile_info);
  618. }
  619. return(FINISHED);
  620. }
  621. /************************* SETUP_SPECANAL_PARAM_RANGES_AND_DEFAULTS *******************/
  622. int setup_specanal_param_ranges_and_defaults(dataptr dz)
  623. {
  624. int exit_status;
  625. aplptr ap = dz->application;
  626. // set_param_ranges()
  627. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  628. // NB total_input_param_cnt is > 0 !!!
  629. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  630. return(FAILED);
  631. // get_param_ranges()
  632. ap->lo[SA_CHANS] = (double)2;
  633. ap->hi[SA_CHANS] = (double)PA_MAX_PVOC_CHANS;
  634. ap->default_val[SA_CHANS] = PA_DEFAULT_PVOC_CHANS;
  635. ap->lo[SA_WINOVLP] = (double)1;
  636. ap->hi[SA_WINOVLP] = (double)4;
  637. ap->default_val[SA_WINOVLP] = 0.0;
  638. if(dz->mode == SA_FORMANTS) {
  639. ap->lo[SA_FORMANT_BANDS] = (double)1;
  640. ap->hi[SA_FORMANT_BANDS] = (double)12;
  641. ap->default_val[SA_FORMANT_BANDS] = 4.0;
  642. } else {
  643. if (dz->mode == SA_FILTER || dz->mode == SA_HFVARY) {
  644. ap->lo[SA_PKCNT] = 1;
  645. ap->hi[SA_PKCNT] = 128;
  646. ap->default_val[SA_PKCNT] = 6;
  647. }
  648. if (dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
  649. ap->lo[SA_TSTEP] = 5;
  650. ap->hi[SA_TSTEP] = (dz->duration/2.0) * SECS_TO_MS;
  651. ap->default_val[SA_TSTEP] = 100;
  652. ap->lo[SA_BOTRANGE] = 0;
  653. ap->hi[SA_BOTRANGE] = 127;
  654. ap->default_val[SA_BOTRANGE] = 0;
  655. ap->lo[SA_TOPRANGE] = 0;
  656. ap->hi[SA_TOPRANGE] = 127;
  657. ap->default_val[SA_TOPRANGE] = 127;
  658. ap->lo[SA_GATE] = 0;
  659. ap->hi[SA_GATE] = 0.5;
  660. ap->default_val[SA_GATE] = 0.1;
  661. }
  662. }
  663. dz->maxmode = 10;
  664. if(!sloom)
  665. put_default_vals_in_all_params(dz);
  666. return(FINISHED);
  667. }
  668. /********************************* PARSE_SLOOM_DATA *********************************/
  669. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  670. {
  671. int exit_status;
  672. int cnt = 1, infilecnt;
  673. int filesize, insams, inbrksize;
  674. double dummy;
  675. int true_cnt = 0;
  676. aplptr ap;
  677. while(cnt<=PRE_CMDLINE_DATACNT) {
  678. if(cnt > argc) {
  679. sprintf(errstr,"Insufficient data sent from TK\n");
  680. return(DATA_ERROR);
  681. }
  682. switch(cnt) {
  683. case(1):
  684. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  685. sprintf(errstr,"Cannot read process no. sent from TK\n");
  686. return(DATA_ERROR);
  687. }
  688. break;
  689. case(2):
  690. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  691. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  692. return(DATA_ERROR);
  693. }
  694. if(dz->mode > 0)
  695. dz->mode--;
  696. //setup_particular_application() =
  697. if((exit_status = setup_specanal_application(dz))<0)
  698. return(exit_status);
  699. ap = dz->application;
  700. break;
  701. case(3):
  702. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  703. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  704. return(DATA_ERROR);
  705. }
  706. if(infilecnt < 1) {
  707. true_cnt = cnt + 1;
  708. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  709. }
  710. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  711. return(exit_status);
  712. break;
  713. case(INPUT_FILETYPE+4):
  714. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  715. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  716. return(DATA_ERROR);
  717. }
  718. break;
  719. case(INPUT_FILESIZE+4):
  720. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  721. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  722. return(DATA_ERROR);
  723. }
  724. dz->insams[0] = filesize;
  725. break;
  726. case(INPUT_INSAMS+4):
  727. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  728. sprintf(errstr,"Cannot read insams sent from TK\n");
  729. return(DATA_ERROR);
  730. }
  731. dz->insams[0] = insams;
  732. break;
  733. case(INPUT_SRATE+4):
  734. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  735. sprintf(errstr,"Cannot read srate sent from TK\n");
  736. return(DATA_ERROR);
  737. }
  738. break;
  739. case(INPUT_CHANNELS+4):
  740. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  741. sprintf(errstr,"Cannot read channels sent from TK\n");
  742. return(DATA_ERROR);
  743. }
  744. break;
  745. case(INPUT_STYPE+4):
  746. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  747. sprintf(errstr,"Cannot read stype sent from TK\n");
  748. return(DATA_ERROR);
  749. }
  750. break;
  751. case(INPUT_ORIGSTYPE+4):
  752. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  753. sprintf(errstr,"Cannot read origstype sent from TK\n");
  754. return(DATA_ERROR);
  755. }
  756. break;
  757. case(INPUT_ORIGRATE+4):
  758. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  759. sprintf(errstr,"Cannot read origrate sent from TK\n");
  760. return(DATA_ERROR);
  761. }
  762. break;
  763. case(INPUT_MLEN+4):
  764. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  765. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  766. return(DATA_ERROR);
  767. }
  768. break;
  769. case(INPUT_DFAC+4):
  770. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  771. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  772. return(DATA_ERROR);
  773. }
  774. break;
  775. case(INPUT_ORIGCHANS+4):
  776. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  777. sprintf(errstr,"Cannot read origchans sent from TK\n");
  778. return(DATA_ERROR);
  779. }
  780. break;
  781. case(INPUT_SPECENVCNT+4):
  782. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  783. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  784. return(DATA_ERROR);
  785. }
  786. dz->specenvcnt = dz->infile->specenvcnt;
  787. break;
  788. case(INPUT_WANTED+4):
  789. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  790. sprintf(errstr,"Cannot read wanted sent from TK\n");
  791. return(DATA_ERROR);
  792. }
  793. break;
  794. case(INPUT_WLENGTH+4):
  795. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  796. sprintf(errstr,"Cannot read wlength sent from TK\n");
  797. return(DATA_ERROR);
  798. }
  799. break;
  800. case(INPUT_OUT_CHANS+4):
  801. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  802. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  803. return(DATA_ERROR);
  804. }
  805. break;
  806. /* RWD these chanegs to samps - tk will have to deal with that! */
  807. case(INPUT_DESCRIPTOR_BYTES+4):
  808. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  809. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  810. return(DATA_ERROR);
  811. }
  812. break;
  813. case(INPUT_IS_TRANSPOS+4):
  814. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  815. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  816. return(DATA_ERROR);
  817. }
  818. break;
  819. case(INPUT_COULD_BE_TRANSPOS+4):
  820. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  821. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  822. return(DATA_ERROR);
  823. }
  824. break;
  825. case(INPUT_COULD_BE_PITCH+4):
  826. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  827. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  828. return(DATA_ERROR);
  829. }
  830. break;
  831. case(INPUT_DIFFERENT_SRATES+4):
  832. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  833. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  834. return(DATA_ERROR);
  835. }
  836. break;
  837. case(INPUT_DUPLICATE_SNDS+4):
  838. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  839. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  840. return(DATA_ERROR);
  841. }
  842. break;
  843. case(INPUT_BRKSIZE+4):
  844. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  845. sprintf(errstr,"Cannot read brksize sent from TK\n");
  846. return(DATA_ERROR);
  847. }
  848. if(inbrksize > 0) {
  849. switch(dz->input_data_type) {
  850. case(WORDLIST_ONLY):
  851. break;
  852. case(PITCH_AND_PITCH):
  853. case(PITCH_AND_TRANSPOS):
  854. case(TRANSPOS_AND_TRANSPOS):
  855. dz->tempsize = inbrksize;
  856. break;
  857. case(BRKFILES_ONLY):
  858. case(UNRANGED_BRKFILE_ONLY):
  859. case(DB_BRKFILES_ONLY):
  860. case(ALL_FILES):
  861. case(ANY_NUMBER_OF_ANY_FILES):
  862. if(dz->extrabrkno < 0) {
  863. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  864. return(DATA_ERROR);
  865. }
  866. if(dz->brksize == NULL) {
  867. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  868. return(PROGRAM_ERROR);
  869. }
  870. dz->brksize[dz->extrabrkno] = inbrksize;
  871. break;
  872. default:
  873. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  874. dz->input_data_type);
  875. return(PROGRAM_ERROR);
  876. }
  877. break;
  878. }
  879. break;
  880. case(INPUT_NUMSIZE+4):
  881. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  882. sprintf(errstr,"Cannot read numsize sent from TK\n");
  883. return(DATA_ERROR);
  884. }
  885. break;
  886. case(INPUT_LINECNT+4):
  887. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  888. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  889. return(DATA_ERROR);
  890. }
  891. break;
  892. case(INPUT_ALL_WORDS+4):
  893. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  894. sprintf(errstr,"Cannot read all_words sent from TK\n");
  895. return(DATA_ERROR);
  896. }
  897. break;
  898. case(INPUT_ARATE+4):
  899. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  900. sprintf(errstr,"Cannot read arate sent from TK\n");
  901. return(DATA_ERROR);
  902. }
  903. break;
  904. case(INPUT_FRAMETIME+4):
  905. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  906. sprintf(errstr,"Cannot read frametime sent from TK\n");
  907. return(DATA_ERROR);
  908. }
  909. dz->frametime = (float)dummy;
  910. break;
  911. case(INPUT_WINDOW_SIZE+4):
  912. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  913. sprintf(errstr,"Cannot read window_size sent from TK\n");
  914. return(DATA_ERROR);
  915. }
  916. break;
  917. case(INPUT_NYQUIST+4):
  918. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  919. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  920. return(DATA_ERROR);
  921. }
  922. break;
  923. case(INPUT_DURATION+4):
  924. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  925. sprintf(errstr,"Cannot read duration sent from TK\n");
  926. return(DATA_ERROR);
  927. }
  928. break;
  929. case(INPUT_MINBRK+4):
  930. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  931. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  932. return(DATA_ERROR);
  933. }
  934. break;
  935. case(INPUT_MAXBRK+4):
  936. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  937. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  938. return(DATA_ERROR);
  939. }
  940. break;
  941. case(INPUT_MINNUM+4):
  942. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  943. sprintf(errstr,"Cannot read minnum sent from TK\n");
  944. return(DATA_ERROR);
  945. }
  946. break;
  947. case(INPUT_MAXNUM+4):
  948. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  949. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  950. return(DATA_ERROR);
  951. }
  952. break;
  953. default:
  954. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  955. return(PROGRAM_ERROR);
  956. }
  957. cnt++;
  958. }
  959. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  960. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  961. return(DATA_ERROR);
  962. }
  963. if(true_cnt)
  964. cnt = true_cnt;
  965. *cmdlinecnt = 0;
  966. while(cnt < argc) {
  967. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  968. return(exit_status);
  969. cnt++;
  970. }
  971. return(FINISHED);
  972. }
  973. /********************************* GET_TK_CMDLINE_WORD *********************************/
  974. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  975. {
  976. if(*cmdlinecnt==0) {
  977. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  978. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  979. return(MEMORY_ERROR);
  980. }
  981. } else {
  982. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  983. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  984. return(MEMORY_ERROR);
  985. }
  986. }
  987. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  988. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  989. return(MEMORY_ERROR);
  990. }
  991. strcpy((*cmdline)[*cmdlinecnt],q);
  992. (*cmdlinecnt)++;
  993. return(FINISHED);
  994. }
  995. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  996. int assign_file_data_storage(int infilecnt,dataptr dz)
  997. {
  998. int exit_status;
  999. int no_sndfile_system_files = FALSE;
  1000. dz->infilecnt = infilecnt;
  1001. if((exit_status = allocate_filespace(dz))<0)
  1002. return(exit_status);
  1003. if(no_sndfile_system_files)
  1004. dz->infilecnt = 0;
  1005. return(FINISHED);
  1006. }
  1007. /************************* redundant functions: to ensure libs compile OK *******************/
  1008. int assign_process_logic(dataptr dz)
  1009. {
  1010. return(FINISHED);
  1011. }
  1012. void set_legal_infile_structure(dataptr dz)
  1013. {}
  1014. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  1015. {
  1016. return(FINISHED);
  1017. }
  1018. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1019. {
  1020. return(FINISHED);
  1021. }
  1022. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1023. {
  1024. return(FINISHED);
  1025. }
  1026. int read_special_data(char *str,dataptr dz)
  1027. {
  1028. return(FINISHED);
  1029. }
  1030. int inner_loop
  1031. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1032. {
  1033. return(FINISHED);
  1034. }
  1035. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1036. {
  1037. return(FINISHED);
  1038. }
  1039. /******************************** USAGE1 ********************************/
  1040. int usage1(void)
  1041. {
  1042. usage2("specanal");
  1043. return(USAGE_ONLY);
  1044. }
  1045. /**************************** CHECK_SPECANAL_PARAM_VALIDITY_AND_CONSISTENCY *****************************/
  1046. int check_specanal_param_validity_and_consistency(dataptr dz)
  1047. {
  1048. int exit_status;
  1049. dz->is_mapping = 0;
  1050. (dz->iparam[SA_WINOVLP])--;
  1051. dz->iparam[SA_CHANS] = dz->iparam[SA_CHANS] + (dz->iparam[SA_CHANS]%4); // Force number of chans to be divisible by 4 (FFT happens twice for cepstrum)
  1052. dz->wanted = dz->iparam[SA_CHANS] + 2;
  1053. if(dz->mode == SA_FORMANTS) {
  1054. if((exit_status = sa_initialise_specenv(dz)) < 0)
  1055. return(exit_status);
  1056. if((exit_status = sa_set_specenv_frqs(dz)) < 0)
  1057. return(exit_status);
  1058. } else if (dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
  1059. if(dz->iparam[SA_BOTRANGE] >= dz->iparam[SA_TOPRANGE] - 12) {
  1060. sprintf(errstr,"INVALID PITCH RANGE: MUST BE > 1 Octave\n");
  1061. return DATA_ERROR;
  1062. }
  1063. if(dz->vflag[SA_DOWNOCT] && dz->vflag[SA_DOWN2OCT]) {
  1064. sprintf(errstr,"CANNOT TRANSPOSE DOWN BY 8va ~AND~ BY TWO 8vas\n");
  1065. return DATA_ERROR;
  1066. }
  1067. } else if (dz->mode == SA_FILTER) {
  1068. if(dz->vflag[SA_DDOWNOCT] && dz->vflag[SA_DDOWN2OCT]) {
  1069. sprintf(errstr,"CANNOT TRANSPOSE DOWN BY 8va ~AND~ BY TWO 8vas\n");
  1070. return DATA_ERROR;
  1071. }
  1072. }
  1073. return FINISHED;
  1074. }
  1075. /**************************** CHECK_SPECANAL_PARAM_VALIDITY_AND_CONSISTENCY_2 *****************************/
  1076. int check_specanal_param_validity_and_consistency2(dataptr dz)
  1077. {
  1078. int exit_status, n;
  1079. dz->param[SA_TSTEP] = dz->param[SA_TSTEP] * MS_TO_SECS;
  1080. dz->framecnt = (int)round(dz->param[SA_TSTEP]/dz->frametime);
  1081. dz->param[SA_TSTEP] = dz->framecnt * dz->frametime;
  1082. dz->iparam[SA_TSTEP] = (int)round(dz->param[SA_TSTEP] * dz->infile->srate);
  1083. dz->envcnt = dz->insams[0]/dz->iparam[SA_TSTEP];
  1084. if(dz->envcnt * dz->iparam[SA_TSTEP] < dz->insams[0])
  1085. dz->envcnt++;
  1086. if((dz->env = (float *)calloc(dz->envcnt + SAFETY,sizeof(float))) == 0) {
  1087. sprintf(errstr, "Can't allocate buffer for reading envelope.\n");
  1088. return(MEMORY_ERROR);
  1089. }
  1090. memset((char *)dz->env,0,(dz->envcnt + SAFETY) * sizeof(float));
  1091. // Buffer for reading sndfile to get envelope
  1092. if((dz->sampbuf = (float **)malloc(sizeof(float *)))==NULL) {
  1093. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers for extracting envelope.(1)\n");
  1094. return(MEMORY_ERROR);
  1095. }
  1096. if((dz->sampbuf[0] = (float *)malloc((dz->iparam[SA_TSTEP] * 2) * sizeof(float)))==NULL) {
  1097. sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers for extracting envelope.(2)\n");
  1098. return(MEMORY_ERROR);
  1099. }
  1100. if((exit_status = extract_env_from_sndfile(dz)) < 0)
  1101. return(exit_status);
  1102. if((dz->iparray = (int **)malloc(8 * sizeof(int *)))==NULL) {
  1103. sprintf(errstr,"INSUFFICIENT MEMORY establishing peaks data storage 0\n");
  1104. return(MEMORY_ERROR);
  1105. }
  1106. if((dz->iparray[0] = (int *)malloc((dz->envcnt+SAFETY) * sizeof(int)))==NULL) {
  1107. sprintf(errstr,"INSUFFICIENT MEMORY establishing peaks data storage 1\n");
  1108. return(MEMORY_ERROR);
  1109. }
  1110. if(dz->mode == SA_HFVARY) {
  1111. for(n=1; n < 8;n++) {
  1112. if((dz->iparray[n] = (int *)malloc((dz->envcnt+SAFETY) * sizeof(int)))==NULL) {
  1113. sprintf(errstr,"INSUFFICIENT MEMORY establishing peaks data storage %d\n",n+1);
  1114. return(MEMORY_ERROR);
  1115. }
  1116. }
  1117. }
  1118. if((dz->parray = (double **)malloc(8 * sizeof(double *)))==NULL) {
  1119. sprintf(errstr,"INSUFFICIENT MEMORY establishing pitch data storage 0\n");
  1120. return(MEMORY_ERROR);
  1121. }
  1122. if((dz->parray[0] = (double *)malloc((dz->envcnt+SAFETY) * 2 * sizeof(double)))==NULL) {
  1123. sprintf(errstr,"INSUFFICIENT MEMORY establishing pitch data storage 1\n");
  1124. return(MEMORY_ERROR);
  1125. }
  1126. if(dz->mode == SA_HFVARY) {
  1127. for(n=1; n < dz->iparam[SA_PKCNT];n++) {
  1128. if((dz->parray[n] = (double *)malloc((dz->envcnt+SAFETY) * 2 * sizeof(double)))==NULL) {
  1129. sprintf(errstr,"INSUFFICIENT MEMORY establishing pitch data storage %d\n",n+1);
  1130. return(MEMORY_ERROR);
  1131. }
  1132. }
  1133. }
  1134. dz->pitchcnt = 0;
  1135. return FINISHED;
  1136. }
  1137. /******************************** DBTOLEVEL ***********************/
  1138. double dbtolevel(double val)
  1139. {
  1140. int isneg = 0;
  1141. if(flteq(val,0.0))
  1142. return(1.0);
  1143. if(val < 0.0) {
  1144. val = -val;
  1145. isneg = 1;
  1146. }
  1147. val /= 20.0;
  1148. val = pow(10.0,val);
  1149. if(isneg)
  1150. val = 1.0/val;
  1151. return(val);
  1152. }
  1153. /********************************************************************************************/
  1154. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1155. {
  1156. if(!strcmp(prog_identifier_from_cmdline,"specanal")) dz->process = SPECANAL;
  1157. else {
  1158. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  1159. return(USAGE_ONLY);
  1160. }
  1161. return(FINISHED);
  1162. }
  1163. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  1164. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  1165. {
  1166. int n;
  1167. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  1168. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  1169. return(MEMORY_ERROR);
  1170. }
  1171. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  1172. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  1173. return(MEMORY_ERROR);
  1174. }
  1175. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1176. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  1177. return(MEMORY_ERROR);
  1178. }
  1179. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1180. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  1181. return(MEMORY_ERROR);
  1182. }
  1183. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1184. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  1185. return(MEMORY_ERROR);
  1186. }
  1187. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  1188. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  1189. return(MEMORY_ERROR);
  1190. }
  1191. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  1192. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  1193. return(MEMORY_ERROR);
  1194. }
  1195. for(n=0;n<brkcnt;n++) {
  1196. dz->brk[n] = NULL;
  1197. dz->brkptr[n] = NULL;
  1198. dz->brkinit[n] = 0;
  1199. dz->brksize[n] = 0;
  1200. }
  1201. return(FINISHED);
  1202. }
  1203. /******************************** USAGE2 ********************************/
  1204. int usage2(char *str)
  1205. {
  1206. if(!strcmp(str,"specanal")) {
  1207. fprintf(stderr,
  1208. "Generate various types of analysis data, or filter data from sound.\n"
  1209. "\n"
  1210. "USAGE:\n"
  1211. "specanal specanal 1 inf analofil chs ovlp\n"
  1212. "specanal specanal 2,4,5 inf txtofils chs ovlp [-n]\n"
  1213. "specanal specanal 3 inf txtofils chs ovlp [-n] [-f]\n"
  1214. "specanal specanal 6 inf txtofils chs ovlp fbands [-n]\n"
  1215. "specanal specanal 7 inf txtofil chs ovlp\n"
  1216. "specanal specanal 8 inf txtofil chs ovlp pkcnt [-a] [-h] [-c] [-m] [-d|-D]\n"
  1217. "specanal specanal 9 inf txtofil chs ovlp tstep [-bbot] [-ttop] [-ggate]\n"
  1218. "specanal specanal 10 inf txtofil chs ovlp pkcnt tstep [-bbot] [-ttop] [-ggate] [-d|-D]\n"
  1219. "\n"
  1220. "INF A Mono soundfile.\n"
  1221. "TXTOFIL(S) (Generic) name for text output file(s).\n"
  1222. "ANALOFIL Analysis output file.\n"
  1223. "CHS Number of analysis points : a multiple of 4 (4 - 16380).\n"
  1224. "OVLP analysis window overlap (1-4), for PVOC analysis.\n"
  1225. "FBANDS Number of formant peaks to find.\n"
  1226. "-n Normalise output display.\n"
  1227. "-f Force frequencies into ascending order.\n"
  1228. "\n"
  1229. "Mode 1: PVOC anal output as analfile.\n"
  1230. "\n"
  1231. "Modes 2-6 generate sets of text outfiles, 1 for each analysis window from input\n"
  1232. " (except first - zeroed - window).\n"
  1233. " These can be used to run a \"movie\" of the data in Soundloom.\n"
  1234. "\n"
  1235. "Mode 2: FFT data as magnitude and channel centre frequency.\n"
  1236. "Mode 3: PVOC data as amplitude and frequency.\n"
  1237. "Mode 4: LOG of FFT magnitudes (output always noremalised).\n"
  1238. "Mode 5: Cepstrum (FFT of log FFT) (output always normalised).\n"
  1239. "Mode 6: Generate Formant Envelope.\n"
  1240. "\n"
  1241. "Modes 7-10 generate 1 textfile, a MIDI list, or a MIDI varibank filterdata file.\n"
  1242. "\n"
  1243. "Mode 7: Signal level, at each semitone bin, averaged over entire sound.\n"
  1244. "Mode 8: Derived Harmonic Field (HF) of entire sound\n"
  1245. " converted to varibank-filter data, or a list of MIDI values.\n"
  1246. "Mode 9: (Changing) Pitch, in tempered scale: output as MIDI-type varibank file.\n"
  1247. " NB Pitch of most prominent partial, not necessarily of fundamental.\n"
  1248. "Mode 10: (Changing) HF in tempered scale: output as MIDI-type varibank file.\n"
  1249. "\n"
  1250. "PKCNT Number of peaks to use as filter frequencies.\n"
  1251. " (Run Mode 7 first to view the spectral envelope as a brkfile).\n"
  1252. "TSTEP Time step, in mS, between pitch-assessments.\n"
  1253. "BOT Minimum acceptable pitch (MIDI).\n"
  1254. "TOP Maximum acceptable pitch (MIDI).\n"
  1255. "GATE Level (relative to max) at which signal ignored (no pitch assigned).\n"
  1256. "-a Ignore relative amp of peaks (dflt, use relative amps) in filter definition.\n"
  1257. "-h Eliminate any peaks which are harmonics of others.\n"
  1258. "-c Dechromaticise: remove quieter pitch of any pair at semitone interval.\n"
  1259. "-m Outputs list of MIDI values (default: MIDI-type varibank filter file).\n"
  1260. "-d Transpose entire filter down by an octave.\n"
  1261. "-D Transpose entire filter down by two octaves.\n"
  1262. "\n");
  1263. } else {
  1264. fprintf(stdout,"Unknown option '%s'\n",str);
  1265. fflush(stdout);
  1266. }
  1267. return(USAGE_ONLY);
  1268. }
  1269. int usage3(char *str1,char *str2)
  1270. {
  1271. fprintf(stderr,"Insufficient parameters on command line.\n");
  1272. return(USAGE_ONLY);
  1273. }
  1274. /****************************** GET_MODE *********************************/
  1275. int get_the_mode_from_cmdline(char *str,dataptr dz)
  1276. {
  1277. char temp[200], *p;
  1278. if(sscanf(str,"%s",temp)!=1) {
  1279. sprintf(errstr,"Cannot read mode of program.\n");
  1280. return(USAGE_ONLY);
  1281. }
  1282. p = temp + strlen(temp) - 1;
  1283. while(p >= temp) {
  1284. if(!isdigit(*p)) {
  1285. fprintf(stderr,"Invalid mode of program entered.\n");
  1286. return(USAGE_ONLY);
  1287. }
  1288. p--;
  1289. }
  1290. if(sscanf(str,"%d",&dz->mode)!=1) {
  1291. fprintf(stderr,"Cannot read mode of program.\n");
  1292. return(USAGE_ONLY);
  1293. }
  1294. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  1295. fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  1296. return(USAGE_ONLY);
  1297. }
  1298. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  1299. return(FINISHED);
  1300. }
  1301. /****************************** HAMMING ******************************/
  1302. void hamming(float *win,int winLen,int even)
  1303. {
  1304. float Pi,ftmp;
  1305. int i;
  1306. /***********************************************************
  1307. Pi = (float)((double)4.*atan((double)1.));
  1308. ***********************************************************/
  1309. Pi = (float)PI;
  1310. ftmp = Pi/winLen;
  1311. if (even) {
  1312. for (i=0; i<winLen; i++)
  1313. *(win+i) = (float)((double).54 + (double).46*cos((double)(ftmp*((float)i+.5))));
  1314. *(win+winLen) = 0.0f;}
  1315. else{ *(win) = 1.0f;
  1316. for (i=1; i<=winLen; i++)
  1317. *(win+i) =(float)((double).54 + (double).46*cos((double)(ftmp*(float)i)));
  1318. }
  1319. return;
  1320. }
  1321. /****************************** FLOAT_ARRAY ******************************/
  1322. int pvoc_float_array(int nnn,float **ptr)
  1323. { /* set up a floating point array length nnn. */
  1324. *ptr = (float *) calloc(nnn,sizeof(float));
  1325. if(*ptr==NULL){
  1326. sprintf(errstr,"specanal: insufficient memory\n");
  1327. return(MEMORY_ERROR);
  1328. }
  1329. return(FINISHED);
  1330. }
  1331. /****************************** INTEGER_ARRAY ******************************/
  1332. int pvoc_integer_array(int nnn,int **ptr)
  1333. { /* set up a floating point array length nnn. */
  1334. *ptr = (int *) calloc(nnn,sizeof(int));
  1335. if(*ptr==NULL){
  1336. sprintf(errstr,"specanal: insufficient memory\n");
  1337. return(MEMORY_ERROR);
  1338. }
  1339. return(FINISHED);
  1340. }
  1341. /****************************** SPECANAL ******************************/
  1342. int specanal(dataptr dz)
  1343. {
  1344. int exit_status, filtercnt, bincnt, n, q, qq, harmonic_amongst_loudest_peaks, peakmidi, chromcnt, downtranspos;
  1345. double rratio, level, centrefrq, frq, range,
  1346. maxsample = 0.0, minsample = 0.0, offset = 0.0, normaliser = 1.0; /* normalisation variables */
  1347. char tempstr[24000], tempstr2[128];
  1348. float *input, /* pointer to start of input buffer */
  1349. *anal, /* pointer to start of analysis buffer */
  1350. *banal, /* pointer to anal[1] (for FFT calls) */
  1351. *averages=NULL, /* pointer to array storing average level of signal in semitone-bins */
  1352. *averages2=NULL,/* pointer to array storing average level of signal in semitone-bins */
  1353. *averages3=NULL,/* pointer to array storing average level of signal in semitone-bins */
  1354. *nextIn, /* pointer to next empty word in input */
  1355. *analWindow, /* pointer to center of analysis window */
  1356. *i0, /* pointer to amplitude channels */
  1357. *i1, /* pointer to frequency channels */
  1358. *oi, /* pointer to old phase channels */
  1359. *oldInPhase, /* pointer to start of input phase buffer */
  1360. *sbuf = NULL, /* input buffer array and pointer */
  1361. *sp;
  1362. int M = 0, /* length of analWindow impulse response */
  1363. D = 0, /* decimatin factor */
  1364. /* RWD */
  1365. /*F = 0,*/ /* fundamental frequency (determines dz->iparam[SA_CHANS]) */
  1366. analWinLen, /* half-length of analysis window */
  1367. i,j,k,kk,jj, /* index variables */
  1368. Dd, /* number of new inputs to read (Dd <= D) */
  1369. N2, /* dz->iparam[SA_CHANS]/2 */
  1370. Mf = 0, /* flag for even M */
  1371. flag = 0, /* end-of-input flag */
  1372. got, /* variables for keeping track of input */
  1373. tocp,
  1374. outframecnt, /* and counting output */
  1375. curtailed = 0,
  1376. normalised = 0, /* flags to keep track of file and normalisation types */
  1377. ordered = 0, /* if set, listed frequencies arranged in ascending order */
  1378. is_text_out = 0,
  1379. is_single_text_out = 0, /* pitch analysis procedures */
  1380. is_anal_out = 0,
  1381. *peaks=NULL,
  1382. doskip,
  1383. zeros = 0;
  1384. int sampsize, /* sample size for output file */
  1385. ibuflen, /* length of input buffer */
  1386. nI = 0, /* current input (analysis) sample */
  1387. origsize = 0, /* sample type of file analysed */
  1388. isr, /* sampling rate */
  1389. Nchans, /* no of chans */
  1390. endsamp = PA_VERY_BIG_INT;
  1391. float real, /* real part of analysis data */
  1392. imag, /* imaginary part of analysis data */
  1393. mag, /* magnitude of analysis data */
  1394. phase, /* phase of analysis data */
  1395. angleDif, /* angle difference */
  1396. RoverTwoPi, /* R/D divided by 2*Pi */
  1397. sum, /* scale factor for renormalizing windows */
  1398. rIn, /* decimated sampling rate */
  1399. R, /* input sampling rate */
  1400. kfrq,jfrq,temp, /* for data-ordering calculations */
  1401. peakfrq,
  1402. arate, /* sample rate for header on stdout if analysis output */
  1403. F = 0.0f; /*RWD */
  1404. char *p, thisext[200], thisbasnam[200], filename[200], thisnum[64]; /* handling output multiple outputfile names */
  1405. int orig_chans;
  1406. int orig_srate;
  1407. // fft ARRAYS
  1408. float *at, *ck, *bt, *sk;
  1409. int *np;
  1410. int bigenough = 1024, maxpos;
  1411. double maxval;
  1412. if((at = (float *) calloc(bigenough,sizeof(float))) == NULL) {
  1413. sprintf(errstr,"Problem Allocating Array 'at' for FFT\n");
  1414. return(MEMORY_ERROR);
  1415. }
  1416. if((ck = (float *) calloc(bigenough,sizeof(float))) == NULL) {
  1417. sprintf(errstr,"Problem Allocating Array 'ck' for FFT\n");
  1418. return(MEMORY_ERROR);
  1419. }
  1420. if((bt = (float *) calloc(bigenough,sizeof(float))) == NULL) {
  1421. sprintf(errstr,"Problem Allocating Array 'bt' for FFT\n");
  1422. return(MEMORY_ERROR);
  1423. }
  1424. if((sk = (float *) calloc(bigenough,sizeof(float))) == NULL) {
  1425. sprintf(errstr,"Problem Allocating Array 'sk' for FFT\n");
  1426. return(MEMORY_ERROR);
  1427. }
  1428. if((np = (int *) calloc(bigenough,sizeof(int))) == NULL) {
  1429. sprintf(errstr,"Problem Allocating Array 'np' for FFT\n");
  1430. return(MEMORY_ERROR);
  1431. }
  1432. switch(dz->mode) {
  1433. case(SA_FFT):
  1434. case(SA_FORMANTS):
  1435. is_text_out = 1;
  1436. if(dz->vflag[0])
  1437. normalised = 1;
  1438. break;
  1439. case(SA_PVOC):
  1440. is_text_out = 1;
  1441. if(dz->vflag[0])
  1442. normalised = 1;
  1443. if(dz->vflag[1])
  1444. ordered = 1;
  1445. break;
  1446. case(SA_LOGFFT):
  1447. case(SA_CEPSTRUM):
  1448. is_text_out = 1;
  1449. normalised = 1; // Always normalised
  1450. break;
  1451. case(SA_AVERAGE):
  1452. case(SA_TEMPERED):
  1453. case(SA_HFVARY):
  1454. case(SA_FILTER):
  1455. is_single_text_out = 1;
  1456. break;
  1457. default:
  1458. is_anal_out = 1;
  1459. break;
  1460. }
  1461. if(is_text_out || is_single_text_out) {
  1462. p = dz->outfilename; // Get elements of output file names
  1463. while(*p != ENDOFSTR) {
  1464. if(*p == '.') {
  1465. strcpy(thisext,p);
  1466. *p = ENDOFSTR;
  1467. strcpy(thisbasnam,dz->outfilename);
  1468. break;
  1469. }
  1470. p++;
  1471. }
  1472. if(*p == ENDOFSTR) { // If no file extension found, force ".txt"
  1473. strcpy(thisext,".txt");
  1474. strcpy(thisbasnam,dz->outfilename);
  1475. }
  1476. }
  1477. if(sndgetprop(dz->ifd[0],"sample type", (char *) &sampsize, sizeof(int)) < 0){
  1478. sprintf(errstr,"specanal: failure to get sample type\n");
  1479. return(MEMORY_ERROR);
  1480. }
  1481. isr = dz->infile->srate;
  1482. dz->nyquist = isr/2.0;
  1483. R = (float)isr;
  1484. Nchans = dz->infile->channels;
  1485. /*RWD OCT 05 need this to preserved hires infile formats */
  1486. origsize = dz->infile->stype;
  1487. if(flteq(R,0.0)) {
  1488. sprintf(errstr,"Problem: zero sampling rate\n");
  1489. return(DATA_ERROR);
  1490. }
  1491. sampsize = SAMP_FLOAT;
  1492. N2 = dz->iparam[SA_CHANS] / 2;
  1493. dz->chwidth = dz->nyquist/(double)N2;
  1494. dz->halfchwidth = dz->chwidth/2;
  1495. F = /*(int)*/(float)(R /(float)dz->iparam[SA_CHANS]); /*RWD*/
  1496. switch(dz->iparam[SA_WINOVLP]){
  1497. case 0: M = 4*dz->iparam[SA_CHANS]; break;
  1498. case 1: M = 2*dz->iparam[SA_CHANS]; break;
  1499. case 2: M = dz->iparam[SA_CHANS]; break;
  1500. case 3: M = N2; break;
  1501. default:
  1502. sprintf(errstr,"specanal: Invalid window overlap factor.\n");
  1503. return(PROGRAM_ERROR);
  1504. }
  1505. Mf = 1 - M%2;
  1506. if (M < 7) {
  1507. fprintf(stdout,"WARNING: analWindow impulse response is too small\n");
  1508. fflush(stdout);
  1509. }
  1510. ibuflen = 4 * M;
  1511. if((D = (int)(M/PA_PVOC_CONSTANT_A)) == 0){
  1512. fprintf(stdout,"WARNING: Decimation too low: adjusted.\n");
  1513. fflush(stdout);
  1514. D = 1;
  1515. }
  1516. arate = (float)(R/D); /* Needed to write to outheader */
  1517. dz->wanted = dz->iparam[SA_CHANS] + 2;
  1518. dz->frametime = (float)(1.0/arate);
  1519. dz->tempsize = dz->insams[0];
  1520. if(dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
  1521. if((exit_status = check_specanal_param_validity_and_consistency2(dz))<0)
  1522. return exit_status;
  1523. if(dz->param[SA_TSTEP] <= dz->frametime * 2) {
  1524. sprintf(errstr,"TIMESTEP TOO SHORT (Minimum > %lf mS)\n",(dz->frametime * 2 * SECS_TO_MS));
  1525. return DATA_ERROR;
  1526. }
  1527. }
  1528. if(is_anal_out) { // Only if Analfile output, write header
  1529. if((exit_status = sndwrite_header(N2,&Nchans,&arate,R,D,origsize,&isr,M,dz))<0)
  1530. return(exit_status);
  1531. dz->process = PVOC_ANAL;
  1532. orig_chans = dz->infile->channels;
  1533. orig_srate = dz->infile->srate;
  1534. dz->infile->channels = dz->outfile->channels;
  1535. dz->infile->srate = dz->outfile->srate;
  1536. if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
  1537. return(exit_status);
  1538. dz->process = SPECANAL;
  1539. dz->infile->channels = orig_chans;
  1540. dz->infile->srate = orig_srate;
  1541. }
  1542. if((exit_status = pvoc_float_array(M+Mf,&analWindow))<0)
  1543. return(exit_status);
  1544. analWindow += (analWinLen = M/2);
  1545. hamming(analWindow,analWinLen,Mf);
  1546. for (i = 1; i <= analWinLen; i++)
  1547. *(analWindow - i) = *(analWindow + i - Mf);
  1548. if (M > dz->iparam[SA_CHANS]) {
  1549. if (Mf)
  1550. *analWindow *=(float)((double)dz->iparam[SA_CHANS]*sin((double)PI*.5/dz->iparam[SA_CHANS])/(double)(PI*.5));
  1551. for (i = 1; i <= analWinLen; i++)
  1552. *(analWindow + i) *=(float)((double)dz->iparam[SA_CHANS] * sin((double) (PI*(i+.5*Mf)/dz->iparam[SA_CHANS])) / (PI*(i+.5*Mf))); /* D.Timis */
  1553. for (i = 1; i <= analWinLen; i++)
  1554. *(analWindow - i) = *(analWindow + i - Mf);
  1555. }
  1556. sum = 0.0f;
  1557. for (i = -analWinLen; i <= analWinLen; i++)
  1558. sum += *(analWindow + i);
  1559. sum = (float)(2.0/sum); /*factor of 2 comes in later in trig identity*/
  1560. for (i = -analWinLen; i <= analWinLen; i++)
  1561. *(analWindow + i) *= sum;
  1562. /* set up input buffer: nextIn always points to the next empty
  1563. word in the input buffer (i.e., the sample following
  1564. sample number (n + analWinLen)). If the buffer is full,
  1565. then nextIn jumps back to the beginning, and the old
  1566. values are written over. */
  1567. if((exit_status = pvoc_float_array(ibuflen,&input))<0)
  1568. return(exit_status);
  1569. nextIn = input;
  1570. /* set up analysis buffer for (N/2 + 1) channels: The input is real,
  1571. so the other channels are redundant. oldInPhase is used
  1572. in the conversion to remember the previous phase when
  1573. calculating phase difference between successive samples. */
  1574. dz->buflen = dz->iparam[SA_CHANS]+2;
  1575. if((exit_status = pvoc_float_array(dz->buflen,&anal))<0)
  1576. return(exit_status);
  1577. banal = anal + 1;
  1578. if((exit_status = pvoc_float_array(N2+1,&oldInPhase))<0)
  1579. return(exit_status);
  1580. if(dz->mode == SA_AVERAGE || dz->mode == SA_FILTER || dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
  1581. if((exit_status = pvoc_float_array((BINCNT+1) * 2,&averages))<0)
  1582. return(exit_status);
  1583. if((exit_status = pvoc_integer_array(BINCNT,&peaks))<0)
  1584. return(exit_status);
  1585. for(n=0;n<BINCNT;n++)
  1586. peaks[n] = -1;
  1587. averages[0] = (float)(miditohz(0)/SEMITONE_INTERVAL);
  1588. for(jj = 1, kk= 2; jj < BINCNT; jj++, kk+=2)
  1589. averages[kk] = (float)miditohz(jj-0.5);
  1590. }
  1591. if(dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
  1592. if((exit_status = pvoc_float_array((BINCNT+1) * 2,&averages2))<0)
  1593. return(exit_status);
  1594. for(jj = 1, kk= 2; jj < BINCNT; jj++, kk+=2)
  1595. averages2[kk] = (float)miditohz(jj-0.5);
  1596. if((exit_status = pvoc_float_array((BINCNT+1) * 2,&averages3))<0)
  1597. return(exit_status);
  1598. for(jj = 1, kk= 2; jj < BINCNT; jj++, kk+=2)
  1599. averages3[kk] = (float)miditohz(jj-0.5);
  1600. }
  1601. /* initialization: input time starts negative so that the rightmost
  1602. edge of the analysis filter just catches the first non-zero
  1603. input samples; output time is always T times input time. */
  1604. rIn = (float)(R/(float)D);
  1605. RoverTwoPi = (float)(rIn/TWOPI);
  1606. nI = -(analWinLen / D) * D; /* input time (in samples) */
  1607. Dd = analWinLen + nI + 1; /* number of new inputs to read */
  1608. flag = 1;
  1609. /* main loop: If endsamp is not specified it is assumed to be very large
  1610. and then readjusted when fgetfloat detects the end of input. */
  1611. display_virtual_time(0L,dz);
  1612. if((sbuf = (float *)calloc(D,sizeof(float))) == 0) {
  1613. sprintf(errstr, "specanal: can't allocate buffer for Dd\n");
  1614. return(MEMORY_ERROR);
  1615. }
  1616. outframecnt = 0;
  1617. if(is_text_out && normalised) { // is_single_text_out uses this to count no of output windows
  1618. // FIND NORMALISER or COUNT OUTPUT WINDOWS
  1619. if(normalised) {
  1620. fprintf(stdout,"Calculating normalisation factor\n");
  1621. fflush(stdout);
  1622. }
  1623. while(nI < (endsamp + analWinLen)){
  1624. /* prepare for analysis: read next Dd input values */
  1625. memset((char *)sbuf,0,Dd*sizeof(float));
  1626. if((got = fgetfbufEx(sbuf, Dd, dz->ifd[0],0)) < 0) {
  1627. sfperror("specanal: read error");
  1628. return(SYSTEM_ERROR);
  1629. }
  1630. if(outframecnt > 0) {
  1631. zeros = 0;
  1632. for(kk=0;kk < Dd;kk++) {
  1633. if(sbuf[kk] == 0.0)
  1634. zeros++;
  1635. }
  1636. }
  1637. if(got < Dd)
  1638. Dd = got;
  1639. if(!is_single_text_out) {
  1640. sp = sbuf;
  1641. tocp = min(got, input+ibuflen-nextIn);
  1642. got -= tocp;
  1643. while(tocp-- > 0)
  1644. *nextIn++ = *sp++;
  1645. if(got > 0) {
  1646. nextIn -= ibuflen;
  1647. while(got-- > 0)
  1648. *nextIn++ = *sp++;
  1649. }
  1650. if (nextIn >= (input + ibuflen))
  1651. nextIn -= ibuflen;
  1652. if (nI > 0) {
  1653. for (i = Dd; i < D; i++){ /* zero fill at EOF */
  1654. *(nextIn++) = 0.0f;
  1655. if (nextIn >= (input + ibuflen))
  1656. nextIn -= ibuflen;
  1657. }
  1658. }
  1659. for (i = 0; i < dz->buflen; i++)
  1660. *(anal + i) = 0.0f; /*initialize*/
  1661. j = (nI - analWinLen - 1 + ibuflen) % ibuflen; /*input pntr*/
  1662. k = nI - analWinLen - 1; /*time shift*/
  1663. while (k < 0)
  1664. k += dz->iparam[SA_CHANS];
  1665. k = k % dz->iparam[SA_CHANS];
  1666. for (i = -analWinLen; i <= analWinLen; i++) { // windowed
  1667. if (++j >= ibuflen)
  1668. j -= ibuflen;
  1669. if (++k >= dz->iparam[SA_CHANS])
  1670. k -= dz->iparam[SA_CHANS];
  1671. *(anal + k) += *(analWindow + i) * *(input + j);
  1672. }
  1673. if((exit_status = fft_(anal,banal,1,N2,1,-2,at,ck,bt,sk,np))<0)
  1674. return(exit_status);
  1675. if((exit_status = reals_(anal,banal,N2,-2))<0)
  1676. return(exit_status);
  1677. if(outframecnt > 0) {
  1678. switch(dz->mode) {
  1679. case(SA_FFT):
  1680. break;
  1681. case(SA_LOGFFT):
  1682. case(SA_CEPSTRUM):
  1683. // Convert to amplitude-phase representation
  1684. for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
  1685. real = *i0;
  1686. imag = *i1;
  1687. mag = (float) sqrt((double)(real * real + imag * imag));
  1688. /* phase unwrapping */
  1689. if (real == 0.0) {
  1690. if(imag==0.0)
  1691. rratio = 0.0;
  1692. else if(imag<0.0)
  1693. rratio = -(PI/2.0);
  1694. else
  1695. rratio = PI/2.0;
  1696. } else {
  1697. rratio = atan((double)imag/(double)real);
  1698. if(real<0.0) {
  1699. if(imag<0.0)
  1700. rratio -= PI;
  1701. else
  1702. rratio += PI;
  1703. }
  1704. }
  1705. phase = (float)rratio;
  1706. *i0 = mag;
  1707. *i1 = phase;
  1708. }
  1709. // Then take log of amplitude ONLY
  1710. for(i=0; i <= N2 * 2; i+=2)
  1711. *(anal + i) = (float)(log(fabs(*(anal + i))));
  1712. if(dz->mode == SA_CEPSTRUM) {
  1713. // Do reconversion to real-imag, similar to PVOC code but without Angle-diff
  1714. for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
  1715. mag = *i0;
  1716. phase = *i1;
  1717. *i0 = (float)((double)mag * cos((double)phase));
  1718. *i1 = (float)((double)mag * sin((double)phase));
  1719. }
  1720. if((exit_status = reals_(anal,banal,N2,2))<0)
  1721. return(exit_status);
  1722. if((exit_status = fft_(anal,banal,1,N2,1,2,at,ck,bt,sk,np))<0)
  1723. return(exit_status);
  1724. for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
  1725. real = *i0;
  1726. imag = *i1;
  1727. mag = (float) sqrt((double)(real * real + imag * imag));
  1728. /* phase unwrapping */
  1729. if (real == 0.0) {
  1730. if(imag==0.0)
  1731. rratio = 0.0;
  1732. else if(imag<0.0)
  1733. rratio = -(PI/2.0);
  1734. else
  1735. rratio = PI/2.0;
  1736. } else {
  1737. rratio = atan((double)imag/(double)real);
  1738. if(real<0.0) {
  1739. if(imag<0.0)
  1740. rratio -= PI;
  1741. else
  1742. rratio += PI;
  1743. }
  1744. }
  1745. phase = (float)rratio;
  1746. *i0 = mag;
  1747. *i1 = phase;
  1748. }
  1749. }
  1750. break;
  1751. case(SA_PVOC):
  1752. case(SA_AVERAGE):
  1753. case(SA_TEMPERED):
  1754. case(SA_HFVARY):
  1755. case(SA_FILTER):
  1756. case(SA_FORMANTS):
  1757. for(i=0,i0=anal,i1=anal+1,oi=oldInPhase; i <= N2; i++,i0+=2,i1+=2,oi++){
  1758. real = *i0;
  1759. imag = *i1;
  1760. *i0 =(float) sqrt((double)(real * real + imag * imag));
  1761. /* phase unwrapping */
  1762. if (*i0 == 0.)
  1763. angleDif = 0.0f;
  1764. else {
  1765. rratio = atan((double)imag/(double)real);
  1766. if(real<0.0) {
  1767. if(imag<0.0)
  1768. rratio -= PI;
  1769. else
  1770. rratio += PI;
  1771. }
  1772. angleDif = (phase = (float)rratio) - *oi;
  1773. *oi = phase;
  1774. }
  1775. if (angleDif > PI)
  1776. angleDif = (float)(angleDif - TWOPI);
  1777. if (angleDif < -PI)
  1778. angleDif = (float)(angleDif + TWOPI);
  1779. /* add in filter center freq.*/
  1780. *i1 = angleDif * RoverTwoPi + ((float) i * F);
  1781. }
  1782. if(dz->mode == SA_FORMANTS) {
  1783. if((exit_status = sa_extract_specenv(anal,dz)) < 0)
  1784. return exit_status;
  1785. }
  1786. break;
  1787. }
  1788. switch(dz->mode) {
  1789. case(SA_FFT): // Output FFT data as channel-centre frq/amp pair
  1790. case(SA_PVOC): // Output PVOC data as frq-amp pair */
  1791. case(SA_LOGFFT):
  1792. case(SA_CEPSTRUM):
  1793. for(kk=0; kk < dz->buflen; kk+= 2) {
  1794. maxsample = max(maxsample,anal[kk]);
  1795. minsample = min(minsample,anal[kk]);
  1796. }
  1797. break;
  1798. case(SA_FORMANTS):
  1799. for(kk=0; kk < dz->infile->specenvcnt; kk++) {
  1800. maxsample = max(maxsample,dz->specenvamp[kk]);
  1801. minsample = min(minsample,dz->specenvamp[kk]);
  1802. }
  1803. break;
  1804. }
  1805. if(curtailed) {
  1806. if(outframecnt == 1) {
  1807. sprintf(errstr,"ERROR: Data in a channel of window at file start is zero, cannot proceed\n");
  1808. return(DATA_ERROR);
  1809. }
  1810. break;
  1811. }
  1812. }
  1813. }
  1814. if(flag /* flag means do this operation only once */
  1815. && (nI > 0) && (Dd < D)){ /* EOF detected */
  1816. flag = 0;
  1817. endsamp = nI + analWinLen - (D - Dd);
  1818. }
  1819. nI += D; /* increment time */
  1820. /* Dd = D except when the end of the sample stream intervenes */
  1821. Dd = min(D, max(0, D+endsamp-nI-analWinLen));
  1822. outframecnt++;
  1823. } /* End of main while loop */
  1824. if(minsample < 0.0)
  1825. offset = -minsample;
  1826. if(flteq(maxsample - minsample,0.0)) {
  1827. sprintf(errstr,"No level found in output data.\n");
  1828. return(DATA_ERROR);
  1829. }
  1830. normaliser = 1.0/(maxsample - minsample);
  1831. outframecnt = 0;
  1832. sndseekEx(dz->ifd[0],0,0);
  1833. nextIn = input;
  1834. nI = -(analWinLen / D) * D;
  1835. Dd = analWinLen + nI + 1;
  1836. flag = 1;
  1837. curtailed = 0;
  1838. endsamp = PA_VERY_BIG_INT;
  1839. }
  1840. while(nI < (endsamp + analWinLen)){
  1841. memset((char *)sbuf,0,Dd*sizeof(float));
  1842. if((got = fgetfbufEx(sbuf, Dd, dz->ifd[0],0)) < 0) {
  1843. sfperror("specanal: read error");
  1844. return(SYSTEM_ERROR);
  1845. }
  1846. if(outframecnt > 0) {
  1847. zeros = 0;
  1848. for(kk=0;kk < Dd;kk++) {
  1849. if(sbuf[kk] == 0.0)
  1850. zeros++;
  1851. }
  1852. if(zeros == Dd) {
  1853. if(dz->mode != SA_AVERAGE && dz->mode != SA_FILTER && dz->mode != SA_TEMPERED && dz->mode != SA_HFVARY) {
  1854. fprintf(stdout,"No Signal at window %d, curtailing analysis here\n",outframecnt);
  1855. fflush(stdout);
  1856. curtailed = 1;
  1857. break;
  1858. }
  1859. }
  1860. }
  1861. if(is_text_out) {
  1862. if(outframecnt > 0) {
  1863. if(outframecnt > 1) // Once first outputfile used
  1864. fclose(dz->fp); // Close it before creating next (last file closed on exit from main)
  1865. strcpy(filename,thisbasnam);
  1866. sprintf(thisnum,"%d",outframecnt);
  1867. strcat(filename,"_"); // Create numbered filename
  1868. strcat(filename,thisnum);
  1869. strcat(filename,thisext);
  1870. if((dz->fp = fopen(filename,"w")) == NULL) {
  1871. sprintf(errstr,"Cannot open output file %s\n", filename);
  1872. return(DATA_ERROR);
  1873. } // Write data to file
  1874. }
  1875. } else if(is_single_text_out) {
  1876. if(outframecnt == 0) {
  1877. strcpy(filename,thisbasnam);
  1878. strcat(filename,thisext);
  1879. if((dz->fp = fopen(filename,"w")) == NULL) {
  1880. sprintf(errstr,"Cannot open output file %s\n", filename);
  1881. return(DATA_ERROR);
  1882. } // Write data to file
  1883. }
  1884. }
  1885. if(got < Dd)
  1886. Dd = got;
  1887. sp = sbuf;
  1888. tocp = min(got, input+ibuflen-nextIn);
  1889. got -= tocp;
  1890. while(tocp-- > 0)
  1891. *nextIn++ = *sp++;
  1892. if(got > 0) {
  1893. nextIn -= ibuflen;
  1894. while(got-- > 0)
  1895. *nextIn++ = *sp++;
  1896. }
  1897. if (nextIn >= (input + ibuflen))
  1898. nextIn -= ibuflen;
  1899. if (nI > 0) {
  1900. for (i = Dd; i < D; i++){ /* zero fill at EOF */
  1901. *(nextIn++) = 0.0f;
  1902. if (nextIn >= (input + ibuflen))
  1903. nextIn -= ibuflen;
  1904. }
  1905. }
  1906. /* ANALYSIS: The analysis subroutine computes the complex output at
  1907. time n of (dz->iparam[SA_CHANS]/2 + 1) of the phase vocoder channels. It operates
  1908. on input samples (n - analWinLen) thru (n + analWinLen) and
  1909. expects to find these in input[(n +- analWinLen) mod ibuflen].
  1910. It expects analWindow to point to the center of a
  1911. symmetric window of length (2 * analWinLen +1). It is the
  1912. responsibility of the main program to ensure that these values
  1913. are correct! The results are returned in anal as succesive
  1914. pairs of real and imaginary values for the lowest (dz->iparam[SA_CHANS]/2 + 1)
  1915. channels. The subroutines fft and reals together implement
  1916. one efficient FFT call for a real input sequence. */
  1917. for (i = 0; i < dz->buflen; i++)
  1918. *(anal + i) = 0.0f; /*initialize*/
  1919. j = (nI - analWinLen - 1 + ibuflen) % ibuflen; /*input pntr*/
  1920. k = nI - analWinLen - 1; /*time shift*/
  1921. while (k < 0)
  1922. k += dz->iparam[SA_CHANS];
  1923. k = k % dz->iparam[SA_CHANS];
  1924. for (i = -analWinLen; i <= analWinLen; i++) {
  1925. if (++j >= ibuflen)
  1926. j -= ibuflen;
  1927. if (++k >= dz->iparam[SA_CHANS])
  1928. k -= dz->iparam[SA_CHANS];
  1929. *(anal + k) += *(analWindow + i) * *(input + j);
  1930. }
  1931. if((exit_status = fft_(anal,banal,1,N2,1,-2,at,ck,bt,sk,np))<0)
  1932. return(exit_status);
  1933. if((exit_status = reals_(anal,banal,N2,-2))<0)
  1934. return(exit_status);
  1935. switch(dz->mode) {
  1936. case(SA_FFT):
  1937. break;
  1938. case(SA_LOGFFT):
  1939. case(SA_CEPSTRUM):
  1940. // Convert to amplitude-phase representation
  1941. for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
  1942. real = *i0;
  1943. imag = *i1;
  1944. mag =(float) sqrt((double)(real * real + imag * imag));
  1945. /* phase unwrapping */
  1946. if (real == 0.0) {
  1947. if(imag == 0.0)
  1948. rratio = 0.0;
  1949. else if(imag<0.0)
  1950. rratio = -(PI/2.0);
  1951. else
  1952. rratio = PI/2.0;
  1953. } else {
  1954. rratio = atan((double)imag/(double)real);
  1955. if(real<0.0) {
  1956. if(imag<0.0)
  1957. rratio -= PI;
  1958. else
  1959. rratio += PI;
  1960. }
  1961. }
  1962. phase = (float)rratio;
  1963. *i0 = mag;
  1964. *i1 = phase;
  1965. }
  1966. // Then take log of amplitude ONLY
  1967. for (i = 0; i <= N2 * 2; i+=2)
  1968. *(anal + i) = (float)(log(fabs(*(anal + i))));
  1969. if(dz->mode == SA_CEPSTRUM) {
  1970. // DO INVERSE conversion to real-imag
  1971. for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
  1972. mag = *i0;
  1973. phase = *i1;
  1974. *i0 = (float)((double)mag * cos((double)phase));
  1975. *i1 = (float)((double)mag * sin((double)phase));
  1976. }
  1977. if((exit_status = reals_(anal,banal,N2,2))<0)
  1978. return(exit_status);
  1979. if((exit_status = fft_(anal,banal,1,N2,1,2,at,ck,bt,sk,np))<0)
  1980. return(exit_status);
  1981. for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
  1982. real = *i0;
  1983. imag = *i1;
  1984. mag = (float) sqrt((double)(real * real + imag * imag));
  1985. /* phase unwrapping */
  1986. if (real == 0.0) {
  1987. if(imag==0.0)
  1988. rratio = 0.0;
  1989. else if(imag<0.0)
  1990. rratio = -(PI/2.0);
  1991. else
  1992. rratio = PI/2.0;
  1993. } else {
  1994. rratio = atan((double)imag/(double)real);
  1995. if(real<0.0) {
  1996. if(imag<0.0)
  1997. rratio -= PI;
  1998. else
  1999. rratio += PI;
  2000. }
  2001. }
  2002. phase = (float)rratio;
  2003. *i0 = mag;
  2004. *i1 = phase;
  2005. }
  2006. }
  2007. break;
  2008. case(SA_PVOC):
  2009. case(SA_AVERAGE):
  2010. case(SA_TEMPERED):
  2011. case(SA_HFVARY):
  2012. case(SA_FILTER):
  2013. case(SA_PVOC_TEST):
  2014. case(SA_FORMANTS):
  2015. /* CONVERSION: The real and imaginary values in anal are converted to
  2016. magnitude and angle-difference-per-second (assuming an
  2017. intermediate sampling rate of rIn) and are returned in
  2018. anal. */
  2019. for(i=0,i0=anal,i1=anal+1,oi=oldInPhase; i <= N2; i++,i0+=2,i1+=2,oi++){
  2020. real = *i0;
  2021. imag = *i1;
  2022. *i0 =(float) sqrt((double)(real * real + imag * imag));
  2023. /* phase unwrapping */
  2024. if (*i0 == 0.)
  2025. angleDif = 0.0f;
  2026. else {
  2027. rratio = atan((double)imag/(double)real);
  2028. if(real<0.0) {
  2029. if(imag<0.0)
  2030. rratio -= PI;
  2031. else
  2032. rratio += PI;
  2033. }
  2034. angleDif = (phase = (float)rratio) - *oi;
  2035. *oi = phase;
  2036. }
  2037. if (angleDif > PI)
  2038. angleDif = (float)(angleDif - TWOPI);
  2039. if (angleDif < -PI)
  2040. angleDif = (float)(angleDif + TWOPI);
  2041. /* add in filter center freq.*/
  2042. *i1 = angleDif * RoverTwoPi + ((float) i * F);
  2043. }
  2044. if(dz->mode == SA_FORMANTS) {
  2045. if((exit_status = sa_extract_specenv(anal,dz)) < 0)
  2046. return exit_status;
  2047. }
  2048. break;
  2049. }
  2050. if(outframecnt == 0) {
  2051. switch(dz->mode) {
  2052. case(SA_PVOC_TEST):
  2053. if((exit_status = write_samps_pvoc(anal, dz->buflen, dz)) < 0)
  2054. return(exit_status);
  2055. break;
  2056. }
  2057. } else {
  2058. switch(dz->mode) {
  2059. case(SA_FFT): // Output FFT data as channel-centre frq/amp pair
  2060. case(SA_LOGFFT):
  2061. case(SA_CEPSTRUM):
  2062. centrefrq = 0.0;
  2063. for(kk=0; kk < dz->buflen; kk+= 2) {
  2064. level = anal[kk];
  2065. if(normalised)
  2066. level = (level + offset) * normaliser;
  2067. if(fprintf(dz->fp,"%f\t%f\n",(float)centrefrq,(float)level)<2) {
  2068. sprintf(errstr,"Problem writing FFT data to file %s\n",filename);
  2069. return(PROGRAM_ERROR);
  2070. }
  2071. centrefrq += dz->chwidth;
  2072. // HEREH: IS THIS THE CORRECT CALCULATION FOR centrefrq
  2073. }
  2074. break;
  2075. case(SA_PVOC): // Output PVOC data as frq-amp pair */
  2076. if(ordered) {
  2077. for(kk=0; kk < dz->buflen-2; kk+= 2) { // Force frq values into ascending order
  2078. kfrq = anal[kk+1]; // So output will display as a brkpnt
  2079. for(jj=kk + 2;jj < dz->buflen;jj += 2) {
  2080. jfrq = anal[jj+1];
  2081. if(jfrq < kfrq) {
  2082. temp = anal[kk+1];
  2083. anal[kk+1] = anal[jj+1];
  2084. anal[jj+1] = temp;
  2085. temp = anal[kk];
  2086. anal[kk] = anal[jj];
  2087. anal[jj] = temp;
  2088. kfrq = jfrq;
  2089. }
  2090. }
  2091. }
  2092. }
  2093. for(kk=0; kk < dz->buflen; kk+= 2) {
  2094. level = anal[kk];
  2095. if(normalised)
  2096. level = (level + offset) * normaliser;
  2097. if(fprintf(dz->fp,"%f\t%f\n",anal[kk+1],(float)level)<2) {
  2098. sprintf(errstr,"Problem writing PVOC data to file %s\n",filename);
  2099. return(PROGRAM_ERROR);
  2100. }
  2101. }
  2102. break;
  2103. case(SA_AVERAGE): // Sum PVOC amplitude in semitonal bins */
  2104. case(SA_TEMPERED):
  2105. case(SA_HFVARY):
  2106. case(SA_FILTER):
  2107. if(dz->mode == SA_TEMPERED) {
  2108. if(outframecnt % dz->framecnt == 0) {
  2109. if((exit_status = get_tempered_pitch(averages,averages2,averages3,dz)) < 0)
  2110. return exit_status;
  2111. }
  2112. } else if(dz->mode == SA_HFVARY) {
  2113. if(outframecnt % dz->framecnt == 0) {
  2114. if((exit_status = get_tempered_hf(averages,averages2,averages3,dz)) < 0)
  2115. return exit_status;
  2116. }
  2117. }
  2118. for(kk=0; kk < dz->buflen; kk+= 2) {
  2119. frq = anal[kk+1];
  2120. level = anal[kk];
  2121. for(jj=0;jj < 256; jj+=2) {
  2122. if(frq < averages[jj]) {
  2123. averages[jj+1] = (float)(averages[jj+1] + level);
  2124. break;
  2125. }
  2126. }
  2127. if(jj >= 256)
  2128. averages[jj+1] = (float)(averages[jj+1] + level);
  2129. }
  2130. break;
  2131. case(SA_FORMANTS): // Output FORMANTS data */
  2132. for(kk=0; kk < dz->infile->specenvcnt; kk++) {
  2133. level = dz->specenvamp[kk];
  2134. if(normalised)
  2135. level = (level + offset) * normaliser;
  2136. if(fprintf(dz->fp,"%f\t%f\n",dz->specenvfrq[kk],(float)level)<2) {
  2137. sprintf(errstr,"Problem writing PVOC data to file %s\n",filename);
  2138. return(PROGRAM_ERROR);
  2139. }
  2140. }
  2141. break;
  2142. case(SA_PVOC_TEST):
  2143. if((exit_status = write_samps_pvoc(anal, dz->buflen, dz)) < 0)
  2144. return(exit_status);
  2145. break;
  2146. }
  2147. }
  2148. if(curtailed) {
  2149. if(is_text_out || (is_single_text_out && (outframecnt == 1))) {
  2150. fclose(dz->fp);
  2151. if(remove(filename) < 0) {
  2152. fprintf(stdout, "ERROR: Can't delete output textfile %s\n",filename);
  2153. fflush(stdout);
  2154. }
  2155. dz->process_type = OTHER_PROCESS; // prevents CDP trying to close non-existent file
  2156. }
  2157. if(outframecnt == 1) {
  2158. fprintf(stdout,"ERROR: Data in window at file start is zero, cannot proceed\n");
  2159. fflush(stdout);
  2160. return(DATA_ERROR);
  2161. }
  2162. break;
  2163. }
  2164. if(flag /* flag means do this operation only once */
  2165. && (nI > 0) && (Dd < D)){ /* EOF detected */
  2166. flag = 0;
  2167. endsamp = nI + analWinLen - (D - Dd);
  2168. }
  2169. nI += D; /* increment time */
  2170. /* Dd = D except when the end of the sample stream intervenes */
  2171. Dd = min(D, max(0, D+endsamp-nI-analWinLen));
  2172. outframecnt++;
  2173. } /* End of main while loop */
  2174. switch(dz->mode) {
  2175. case(SA_AVERAGE): // Output average semitone-amplitude data
  2176. case(SA_FILTER):
  2177. maxsample = 0.0;
  2178. minsample = 0.0;
  2179. for(kk=0; kk < 258; kk+=2) {
  2180. minsample = min(averages[kk+1],minsample);
  2181. maxsample = max(averages[kk+1],maxsample);
  2182. }
  2183. range = maxsample - minsample;
  2184. if(flteq(range,0.0)) {
  2185. sprintf(errstr,"No significant signal found in input sound.\n");
  2186. return(DATA_ERROR);
  2187. }
  2188. for(jj = 0, kk=0; jj < BINCNT; kk+=2, jj++) {
  2189. if(kk == 0)
  2190. averages[kk] = (float)(miditohz(0)/2.0); // i.e. anything below midi zero
  2191. else
  2192. averages[kk] = (float)(miditohz(jj-1)); // i.e. anything around midi jj-1
  2193. averages[kk+1] = (float)((averages[kk+1] - minsample)/range);
  2194. }
  2195. averages[256] = (float)miditohz(127); // i.e. anything at or above midi 127
  2196. averages[257] = (float)((averages[257] - minsample)/range);
  2197. switch(dz->mode) {
  2198. case(SA_AVERAGE):
  2199. for(jj=1,kk=2; jj < BINCNT; jj++, kk+=2) { // Ignore pitches below MIDI 0
  2200. if(fprintf(dz->fp,"%d\t%f\n",(int)round(unchecked_hztomidi(averages[kk])),averages[kk+1])<1) {
  2201. sprintf(errstr,"Problem writing average semitone amplitude data to file %s\n",filename);
  2202. return(PROGRAM_ERROR);
  2203. }
  2204. }
  2205. break;
  2206. case(SA_FILTER):
  2207. for(n = 0; n < BINCNT; n++) { // For every peak-numbering
  2208. maxval = -10000;
  2209. maxpos = 0;
  2210. // For every semitone bin
  2211. for(jj = 0, kk= 0; jj < BINCNT; jj++, kk+=2) {
  2212. doskip = 0;
  2213. if(n>0) {
  2214. for(qq=0;qq<n;qq++) { // If this bin is already a peak
  2215. if(peaks[qq] == jj) {
  2216. doskip = 1;
  2217. break;
  2218. }
  2219. }
  2220. }
  2221. if(doskip)
  2222. continue;
  2223. if(averages[kk+1] > maxval) { // is it the loudest non-listed peak??
  2224. maxval = averages[kk+1];
  2225. maxpos = jj;
  2226. }
  2227. }
  2228. peaks[n] = maxpos; // peaks[n] takes the number of loudest peak amongst those not yet listed
  2229. // peaks array thus becomes listing of peaks in descending loudness order
  2230. }
  2231. for(n = 0; n < BINCNT; n++) { // Move peak at MIDI zero to bottom of peaks list
  2232. if(peaks[n] == 0) {
  2233. for(qq=n+1;qq<BINCNT;qq++)
  2234. peaks[qq-1] = peaks[qq];
  2235. peaks[BINCNT-1] = 0;
  2236. break;
  2237. }
  2238. }
  2239. // If flag set, eliminate peaks a semitone away from more prominent peaks
  2240. if(dz->vflag[SA_DECHROM]) {
  2241. for(q = 0; q < BINCNT; q++) { // For ALL peaks, starting at the loudest
  2242. jj = peaks[q];
  2243. kk = jj*2; // Find the associated frq-amp data
  2244. if(averages[kk] < miditohz(0)) // (if frequency is below midi 0, keep)
  2245. continue;
  2246. peakmidi = (int)round(unchecked_hztomidi(averages[kk])); // Get the midipitch of this peak
  2247. qq = 0;
  2248. chromcnt = 0;
  2249. while(qq < BINCNT) { // Compare this peak with all other peaks
  2250. if(qq != q) {
  2251. jj = peaks[qq];
  2252. kk = jj*2; // If other pitch is a semitone higher or lower
  2253. if((averages[kk] >= 0.0) && (abs((int)round(unchecked_hztomidi(averages[kk])) - peakmidi) == 1)) {
  2254. averages[kk] = -1.0; // Flag less-prominent peak as not-wanted, by setting frq to -1
  2255. for(n=qq+1;n < BINCNT;n++)
  2256. peaks[n-1] = peaks[n]; // Shuffle-down overwrite peak-data (peak eliminated from list)
  2257. peaks[BINCNT-1] = jj; // Eliminated peak goes to bottom of list of peaks
  2258. if(++chromcnt > 1) // No more than 2 semitone-adjacent peaks, so if got 2, drop from inner loop
  2259. break;
  2260. qq--;
  2261. }
  2262. }
  2263. qq++;
  2264. }
  2265. }
  2266. }
  2267. filtercnt = 0;
  2268. if(dz->vflag[SA_NO_HARMONICS]) { // If flag set, eliminate harmonics of peaks, starting at most prominent peak
  2269. do {
  2270. harmonic_amongst_loudest_peaks = 0;
  2271. for(q = 0; q < dz->iparam[SA_PKCNT]; q++) { // For SA_PKCNT peaks, starting at the loudest
  2272. jj = peaks[q];
  2273. kk = jj*2; // Find the associated frq-amp data
  2274. if(flteq(averages[kk],-1.0)) { // If this peak (and hence all the remaining peaks) has already been rejected,
  2275. filtercnt = q; // reset filtercnt and quit.
  2276. break;
  2277. }
  2278. if(averages[kk] < miditohz(0)) // (if frequency is below midi 0, keep)
  2279. continue;
  2280. peakfrq = averages[kk];
  2281. qq = 0;
  2282. while(qq < BINCNT) { // Compare this peak with all other peaks
  2283. if(qq != q) {
  2284. jj = peaks[qq];
  2285. kk = jj*2; // If higher frequency is a harmonic of lower
  2286. if((averages[kk] >= 0.0) && is_a_harmonic_x(averages[kk],peakfrq)) {
  2287. averages[kk] = -1.0; // Flag peak as not-wanted, by setting frq to -1
  2288. for(n=qq+1;n < BINCNT;n++)
  2289. peaks[n-1] = peaks[n]; // Shuffle-down overwrite peak-data (peak eliminated from list)
  2290. peaks[BINCNT-1] = jj; // Eliminated peak goes to bottom of list of peaks
  2291. if(qq < dz->iparam[SA_PKCNT]) // If we have thus eliminated one of the currently loudest SA_PKCNT peaks
  2292. harmonic_amongst_loudest_peaks = 1;
  2293. // Flag that a new search for harmonics is needed, with the new set of SA_PKCNT peaks
  2294. qq--;
  2295. }
  2296. }
  2297. qq++;
  2298. }
  2299. }
  2300. } while(harmonic_amongst_loudest_peaks);
  2301. }
  2302. if(filtercnt == 0) { // If filtercnt has not been reset previously, set it now
  2303. filtercnt = dz->iparam[SA_PKCNT];
  2304. for(n=filtercnt;n < BINCNT;n++) {
  2305. jj = peaks[n];
  2306. kk = jj*2;
  2307. averages[kk] = -1.0; // and set all unwanted peaks to -1
  2308. }
  2309. }
  2310. jj = 0;
  2311. bincnt = BINCNT;
  2312. while(jj < bincnt-1) { // Peaks set to -1 are eliminated by downward-shuffle overwrite
  2313. kk = jj*2;
  2314. if(averages[kk] < 0) {
  2315. for(n = kk;n < (bincnt-1)*2; n++)
  2316. averages[n] = averages[n+2];
  2317. bincnt--;
  2318. } else
  2319. jj++;
  2320. }
  2321. kk = jj*2;
  2322. if(averages[kk] < 0)
  2323. bincnt--;
  2324. if(bincnt != filtercnt) {
  2325. sprintf(errstr,"Error in bin-elimination logic. bincnt = %d filtercnt = %d\n",bincnt,filtercnt);
  2326. return PROGRAM_ERROR;
  2327. }
  2328. // Convert to MIDI
  2329. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2)
  2330. averages[kk] = (float)((int)round(unchecked_hztomidi(averages[kk])));
  2331. // Do any transposition required
  2332. if(dz->vflag[SA_DDOWNOCT]) {
  2333. downtranspos = 1;
  2334. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
  2335. if(averages[kk] - 12.0 < 0) {
  2336. downtranspos = 0;
  2337. break;
  2338. }
  2339. }
  2340. if(!downtranspos) {
  2341. fprintf(stdout,"WARNING: OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
  2342. fflush(stdout);
  2343. } else {
  2344. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2)
  2345. averages[kk] -= 12.0;
  2346. }
  2347. } else if(dz->vflag[SA_DDOWN2OCT]) {
  2348. downtranspos = 2;
  2349. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
  2350. if(averages[kk] - 24.0 < 0) {
  2351. downtranspos = 0;
  2352. break;
  2353. }
  2354. }
  2355. if(!downtranspos) {
  2356. fprintf(stdout,"WARNING: TWO OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
  2357. fflush(stdout);
  2358. } else {
  2359. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2)
  2360. averages[kk] -= 24.0;
  2361. }
  2362. }
  2363. if(dz->vflag[SA_IGNORE_AMP]) { // Ignore amplitudes (set them all to 1.0)
  2364. for(jj=0,kk=1;jj < filtercnt;jj++,kk+=2)
  2365. averages[kk] = 1.0;
  2366. }
  2367. if(dz->vflag[SA_MIDILIST]) {
  2368. sprintf(tempstr,"");
  2369. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
  2370. if((int)round(averages[kk]) >= 0) {
  2371. sprintf(tempstr2,"%d\t",(int)round(averages[kk]));
  2372. strcat(tempstr,tempstr2);
  2373. }
  2374. }
  2375. } else {
  2376. sprintf(tempstr,"0.0\t");
  2377. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
  2378. sprintf(tempstr2,"%d\t%f\t",(int)round(averages[kk]),averages[kk+1]);
  2379. strcat(tempstr,tempstr2);
  2380. }
  2381. if(fprintf(dz->fp,"%s\n",tempstr)<1) {
  2382. sprintf(errstr,"Problem writing filter data to file %s\n",filename);
  2383. return(PROGRAM_ERROR);
  2384. }
  2385. sprintf(tempstr,"10000.0\t");
  2386. for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
  2387. sprintf(tempstr2,"%d\t%f\t",(int)round(averages[kk]),averages[kk+1]);
  2388. strcat(tempstr,tempstr2);
  2389. }
  2390. }
  2391. if(fprintf(dz->fp,"%s\n",tempstr)<1) {
  2392. sprintf(errstr,"Problem writing filter data to file %s\n",filename);
  2393. return(PROGRAM_ERROR);
  2394. }
  2395. break;
  2396. }
  2397. break;
  2398. case(SA_TEMPERED):
  2399. if(outframecnt % dz->framecnt > 0) { // Extract pitch from any part-window at end
  2400. if((exit_status = get_tempered_pitch(averages,averages2,averages3,dz)) < 0)
  2401. return exit_status;
  2402. }
  2403. if((exit_status = smooth_and_output_tempered_pitch(dz))<0)
  2404. return exit_status;
  2405. break;
  2406. case(SA_HFVARY):
  2407. if(outframecnt % dz->framecnt > 0) { // Extract HF from any part-window at end
  2408. if((exit_status = get_tempered_hf(averages,averages2,averages3,dz)) < 0)
  2409. return exit_status;
  2410. }
  2411. if((exit_status = smooth_and_output_varying_hf(dz))<0)
  2412. return exit_status;
  2413. break;
  2414. }
  2415. return(FINISHED);
  2416. }
  2417. /************************************ SNDWRITE_HEADER ************************************/
  2418. int sndwrite_header(int N2,int *Nchans,float *arate,float R,int D,int origsize,int *isr,int M,dataptr dz)
  2419. {
  2420. *Nchans = dz->iparam[SA_CHANS] + 2;
  2421. dz->outfile->channels = *Nchans;
  2422. *arate = (float)(R/(float)D);
  2423. dz->outfile->srate = (int)(*arate);
  2424. dz->outfile->arate = *arate;
  2425. dz->outfile->origstype = origsize;
  2426. dz->outfile->origrate = *isr;
  2427. dz->outfile->Mlen = M;
  2428. dz->outfile->Dfac = D;
  2429. fflush(stdout);
  2430. return(FINISHED);
  2431. }
  2432. /******************************* WRITE_SAMPS_PVOC ********************************/
  2433. int write_samps_pvoc(float *bbuf,int samps_to_write,dataptr dz)
  2434. {
  2435. int samps_written;
  2436. int i,j;
  2437. int granularity = 22100;
  2438. int this_granularity = 0;
  2439. float val;
  2440. if(dz->needpeaks){
  2441. for(i=0;i < samps_to_write; i += dz->outchans){
  2442. for(j = 0;j < dz->outchans;j++){
  2443. val = (float)fabs(bbuf[i+j]);
  2444. /* this way, posiiton of first peak value is stored */
  2445. if(val > dz->outpeaks[j].value){
  2446. dz->outpeaks[j].value = val;
  2447. dz->outpeaks[j].position = dz->outpeakpos[j];
  2448. }
  2449. }
  2450. /* count framepos */
  2451. for(j=0;j < dz->outchans;j++)
  2452. dz->outpeakpos[j]++;
  2453. }
  2454. }
  2455. if((samps_written = fputfbufEx(bbuf,samps_to_write,dz->ofd))<=0) {
  2456. sprintf(errstr,"Can't write to output soundfile: %s\n",sferrstr());
  2457. return(SYSTEM_ERROR);
  2458. }
  2459. dz->total_samps_written += samps_written;
  2460. this_granularity += samps_to_write;
  2461. if(this_granularity > granularity){
  2462. display_virtual_time(dz->total_samps_written,dz);
  2463. this_granularity -= granularity;
  2464. }
  2465. return(FINISHED);
  2466. }
  2467. ///////////// MXFFT
  2468. /*
  2469. *-----------------------------------------------------------------------
  2470. * subroutine: fft
  2471. * multivariate complex fourier transform, computed in place
  2472. * using mixed-radix fast fourier transform algorithm.
  2473. *-----------------------------------------------------------------------
  2474. *
  2475. * this is the call from C:
  2476. * fft_(anal,banal,&one,&N2,&one,&mtwo);
  2477. * CHANGED TO:-
  2478. * fft_(anal,banal,one,N2,one,mtwo);
  2479. */
  2480. int fft_(float *a, float *b, int nseg, int n, int nspn, int isn,float *at,float *ck,float *bt,float *sk,int *np)
  2481. /* a: pointer to array 'anal' */
  2482. /* b: pointer to array 'banal' */
  2483. {
  2484. int exit_status;
  2485. int nfac[16]; /* These are one bigger than needed */
  2486. /* because wish to use Fortran array */
  2487. /* index which runs 1 to n, not 0 to n */
  2488. int m = 0, nf, k, kt, ntot, j, jj, maxf, maxp=0;
  2489. /* work space pointers */
  2490. // float *at, *ck, *bt, *sk;
  2491. // int *np;
  2492. /* reduce the pointers to input arrays - by doing this, FFT uses FORTRAN
  2493. indexing but retains compatibility with C arrays */
  2494. a--; b--;
  2495. /*
  2496. * determine the factors of n
  2497. */
  2498. k=nf=abs(n);
  2499. if(nf==1)
  2500. return(FINISHED);
  2501. nspn=abs(nf*nspn);
  2502. ntot=abs(nspn*nseg);
  2503. if(isn*ntot == 0){
  2504. sprintf(errstr,"zero in FFT parameters %d %d %d %d",nseg, n, nspn, isn);
  2505. return(DATA_ERROR);
  2506. }
  2507. for (m=0; !(k%16); nfac[++m]=4,k/=16);
  2508. for (j=3,jj=9; jj<=k; j+=2,jj=j*j)
  2509. for (; !(k%jj); nfac[++m]=j,k/=jj);
  2510. if (k<=4) {
  2511. kt = m;
  2512. nfac[m+1] = k;
  2513. if(k != 1)
  2514. m++;
  2515. } else {
  2516. if(k%4==0){
  2517. nfac[++m]=2;
  2518. k/=4;
  2519. }
  2520. kt = m;
  2521. maxp = max((kt+kt+2),(k-1));
  2522. for(j=2; j<=k; j=1+((j+1)/2)*2) {
  2523. if(k%j==0){
  2524. nfac[++m]=j;
  2525. k/=j;
  2526. }
  2527. }
  2528. }
  2529. if(m <= kt+1)
  2530. maxp = m + kt + 1;
  2531. if(m+kt > 15) {
  2532. sprintf(errstr,"FFT parameter n has more than 15 factors : %d", n);
  2533. return(DATA_ERROR);
  2534. }
  2535. if(kt!=0) {
  2536. j = kt;
  2537. while(j)
  2538. nfac[++m]=nfac[j--];
  2539. }
  2540. maxf = nfac[m-kt];
  2541. if(kt > 0)
  2542. maxf = max(nfac[kt],maxf);
  2543. /* allocate workspace - assume no errors! */
  2544. // at = (float *) calloc(maxf,sizeof(float));
  2545. // ck = (float *) calloc(maxf,sizeof(float));
  2546. // bt = (float *) calloc(maxf,sizeof(float));
  2547. // sk = (float *) calloc(maxf,sizeof(float));
  2548. // np = (int *) calloc(maxp,sizeof(int));
  2549. /* decrement pointers to allow FORTRAN type usage in fftmx */
  2550. at--; bt--; ck--; sk--; np--;
  2551. /* call fft driver */
  2552. if((exit_status = fftmx(a,b,ntot,nf,nspn,isn,m,&kt,at,ck,bt,sk,np,nfac))<0)
  2553. return(exit_status);
  2554. /* restore pointers before releasing */
  2555. at++; bt++; ck++; sk++; np++;
  2556. /* release working storage before returning - assume no problems */
  2557. // (void) free(at);
  2558. // (void) free(sk);
  2559. // (void) free(bt);
  2560. // (void) free(ck);
  2561. // (void) free(np);
  2562. return(FINISHED);
  2563. }
  2564. /*
  2565. *-----------------------------------------------------------------------
  2566. * subroutine: fftmx
  2567. * called by subroutine 'fft' to compute mixed-radix fourier transform
  2568. *-----------------------------------------------------------------------
  2569. */
  2570. int fftmx(float *a,float *b,int ntot,int n,int nspan,int isn,int m,int *kt,
  2571. float *at,float *ck,float *bt,float *sk,int *np,int nfac[])
  2572. {
  2573. int i,inc,
  2574. j,jc,jf, jj,
  2575. k, k1, k2, k3=0, k4,
  2576. kk,klim,ks,kspan, kspnn,
  2577. lim,
  2578. maxf,mm,
  2579. nn,nt;
  2580. double aa, aj, ajm, ajp, ak, akm, akp,
  2581. bb, bj, bjm, bjp, bk, bkm, bkp,
  2582. c1, c2=0.0, c3=0.0, c72, cd,
  2583. dr,
  2584. rad,
  2585. sd, s1, s2=0.0, s3=0.0, s72, s120;
  2586. double xx; /****** ADDED APRIL 1991 *********/
  2587. inc=abs(isn);
  2588. nt = inc*ntot;
  2589. ks = inc*nspan;
  2590. /******************* REPLACED MARCH 29: ***********************
  2591. rad = atan((double)1.0);
  2592. **************************************************************/
  2593. rad = 0.785398163397448278900;
  2594. /******************* REPLACED MARCH 29: ***********************
  2595. s72 = rad/0.625;
  2596. c72 = cos(s72);
  2597. s72 = sin(s72);
  2598. **************************************************************/
  2599. c72 = 0.309016994374947451270;
  2600. s72 = 0.951056516295153531190;
  2601. /******************* REPLACED MARCH 29: ***********************
  2602. s120 = sqrt((double)0.75);
  2603. **************************************************************/
  2604. s120 = 0.866025403784438707600;
  2605. /* scale by 1/n for isn > 0 ( reverse transform ) */
  2606. if (isn < 0){
  2607. s72 = -s72;
  2608. s120 = -s120;
  2609. rad = -rad;}
  2610. else{ ak = 1.0/(double)n;
  2611. for(j=1; j<=nt;j += inc){
  2612. a[j] = (float)(a[j] * ak);
  2613. b[j] = (float)(b[j] * ak);
  2614. }
  2615. }
  2616. kspan = ks;
  2617. nn = nt - inc;
  2618. jc = ks/n;
  2619. /* sin, cos values are re-initialized each lim steps */
  2620. lim = 32;
  2621. klim = lim * jc;
  2622. i = 0;
  2623. jf = 0;
  2624. maxf = m - (*kt);
  2625. maxf = nfac[maxf];
  2626. if((*kt) > 0)
  2627. maxf = max(nfac[*kt],maxf);
  2628. /*
  2629. * compute fourier transform
  2630. */
  2631. lbl40:
  2632. dr = (8.0 * (double)jc)/((double)kspan);
  2633. /*************************** APRIL 1991 POW & POW2 not WORKING.. REPLACE *******
  2634. cd = 2.0 * (pow2 ( sin((double)0.5 * dr * rad)) );
  2635. *******************************************************************************/
  2636. xx = sin((double)0.5 * dr * rad);
  2637. cd = 2.0 * xx * xx;
  2638. sd = sin(dr * rad);
  2639. kk = 1;
  2640. if(nfac[++i]!=2) goto lbl110;
  2641. /*
  2642. * transform for factor of 2 (including rotation factor)
  2643. */
  2644. kspan /= 2;
  2645. k1 = kspan + 2;
  2646. do{ do{ k2 = kk + kspan;
  2647. ak = a[k2];
  2648. bk = b[k2];
  2649. a[k2] = (float)((a[kk]) - ak);
  2650. b[k2] = (float)((b[kk]) - bk);
  2651. a[kk] = (float)((a[kk]) + ak);
  2652. b[kk] = (float)((b[kk]) + bk);
  2653. kk = k2 + kspan;
  2654. } while(kk <= nn);
  2655. kk -= nn;
  2656. }while(kk <= jc);
  2657. if(kk > kspan) goto lbl350;
  2658. lbl60: c1 = 1.0 - cd;
  2659. s1 = sd;
  2660. mm = min((k1/2),klim);
  2661. goto lbl80;
  2662. lbl70: ak = c1 - ((cd*c1)+(sd*s1));
  2663. s1 = ((sd*c1)-(cd*s1)) + s1;
  2664. c1 = ak;
  2665. lbl80: do{ do{ k2 = kk + kspan;
  2666. ak = a[kk] - a[k2];
  2667. bk = b[kk] - b[k2];
  2668. a[kk] = a[kk] + a[k2];
  2669. b[kk] = b[kk] + b[k2];
  2670. a[k2] = (float)((c1 * ak) - (s1 * bk));
  2671. b[k2] = (float)((s1 * ak) + (c1 * bk));
  2672. kk = k2 + kspan;
  2673. }while(kk < nt);
  2674. k2 = kk - nt;
  2675. c1 = -c1;
  2676. kk = k1 - k2;
  2677. }while(kk > k2);
  2678. kk += jc;
  2679. if(kk <= mm) goto lbl70;
  2680. if(kk < k2) goto lbl90;
  2681. k1 += (inc + inc);
  2682. kk = ((k1-kspan)/2) + jc;
  2683. if(kk <= (jc+jc)) goto lbl60;
  2684. goto lbl40;
  2685. lbl90: s1 = ((double)((kk-1)/jc)) * dr * rad;
  2686. c1 = cos(s1);
  2687. s1 = sin(s1);
  2688. mm = min( k1/2, mm+klim);
  2689. goto lbl80;
  2690. /*
  2691. * transform for factor of 3 (optional code)
  2692. */
  2693. lbl100: k1 = kk + kspan;
  2694. k2 = k1 + kspan;
  2695. ak = a[kk];
  2696. bk = b[kk];
  2697. aj = a[k1] + a[k2];
  2698. bj = b[k1] + b[k2];
  2699. a[kk] = (float)(ak + aj);
  2700. b[kk] = (float)(bk + bj);
  2701. ak += (-0.5 * aj);
  2702. bk += (-0.5 * bj);
  2703. aj = (a[k1] - a[k2]) * s120;
  2704. bj = (b[k1] - b[k2]) * s120;
  2705. a[k1] = (float)(ak - bj);
  2706. b[k1] = (float)(bk + aj);
  2707. a[k2] = (float)(ak + bj);
  2708. b[k2] = (float)(bk - aj);
  2709. kk = k2 + kspan;
  2710. if(kk < nn) goto lbl100;
  2711. kk -= nn;
  2712. if(kk <= kspan) goto lbl100;
  2713. goto lbl290;
  2714. /*
  2715. * transform for factor of 4
  2716. */
  2717. lbl110: if(nfac[i] != 4) goto lbl230;
  2718. kspnn = kspan;
  2719. kspan = kspan/4;
  2720. lbl120: c1 = 1.0;
  2721. s1 = 0;
  2722. mm = min( kspan, klim);
  2723. goto lbl150;
  2724. lbl130: c2 = c1 - ((cd*c1)+(sd*s1));
  2725. s1 = ((sd*c1)-(cd*s1)) + s1;
  2726. /*
  2727. * the following three statements compensate for truncation
  2728. * error. if rounded arithmetic is used, substitute
  2729. * c1=c2
  2730. *
  2731. * c1 = (0.5/(pow2(c2)+pow2(s1))) + 0.5;
  2732. * s1 = c1*s1;
  2733. * c1 = c1*c2;
  2734. */
  2735. c1 = c2;
  2736. lbl140: c2 = (c1 * c1) - (s1 * s1);
  2737. s2 = c1 * s1 * 2.0;
  2738. c3 = (c2 * c1) - (s2 * s1);
  2739. s3 = (c2 * s1) + (s2 * c1);
  2740. lbl150: k1 = kk + kspan;
  2741. k2 = k1 + kspan;
  2742. k3 = k2 + kspan;
  2743. akp = a[kk] + a[k2];
  2744. akm = a[kk] - a[k2];
  2745. ajp = a[k1] + a[k3];
  2746. ajm = a[k1] - a[k3];
  2747. a[kk] = (float)(akp + ajp);
  2748. ajp = akp - ajp;
  2749. bkp = b[kk] + b[k2];
  2750. bkm = b[kk] - b[k2];
  2751. bjp = b[k1] + b[k3];
  2752. bjm = b[k1] - b[k3];
  2753. b[kk] = (float)(bkp + bjp);
  2754. bjp = (float)(bkp - bjp);
  2755. if(isn < 0) goto lbl180;
  2756. akp = akm - bjm;
  2757. akm = akm + bjm;
  2758. bkp = bkm + ajm;
  2759. bkm = bkm - ajm;
  2760. if(s1 == 0.0) goto lbl190;
  2761. lbl160: a[k1] = (float)((akp*c1) - (bkp*s1));
  2762. b[k1] = (float)((akp*s1) + (bkp*c1));
  2763. a[k2] = (float)((ajp*c2) - (bjp*s2));
  2764. b[k2] = (float)((ajp*s2) + (bjp*c2));
  2765. a[k3] = (float)((akm*c3) - (bkm*s3));
  2766. b[k3] = (float)((akm*s3) + (bkm*c3));
  2767. kk = k3 + kspan;
  2768. if(kk <= nt) goto lbl150;
  2769. lbl170: kk -= (nt - jc);
  2770. if(kk <= mm) goto lbl130;
  2771. if(kk < kspan) goto lbl200;
  2772. kk -= (kspan - inc);
  2773. if(kk <= jc) goto lbl120;
  2774. if(kspan==jc) goto lbl350;
  2775. goto lbl40;
  2776. lbl180: akp = akm + bjm;
  2777. akm = akm - bjm;
  2778. bkp = bkm - ajm;
  2779. bkm = bkm + ajm;
  2780. if(s1 != 0.0) goto lbl160;
  2781. lbl190: a[k1] = (float)akp;
  2782. b[k1] = (float)bkp;
  2783. a[k2] = (float)ajp;
  2784. b[k2] = (float)bjp;
  2785. a[k3] = (float)akm;
  2786. b[k3] = (float)bkm;
  2787. kk = k3 + kspan;
  2788. if(kk <= nt) goto lbl150;
  2789. goto lbl170;
  2790. lbl200: s1 = ((double)((kk-1)/jc)) * dr * rad;
  2791. c1 = cos(s1);
  2792. s1 = sin(s1);
  2793. mm = min( kspan, mm+klim);
  2794. goto lbl140;
  2795. /*
  2796. * transform for factor of 5 (optional code)
  2797. */
  2798. lbl210: c2 = (c72*c72) - (s72*s72);
  2799. s2 = 2.0 * c72 * s72;
  2800. lbl220: k1 = kk + kspan;
  2801. k2 = k1 + kspan;
  2802. k3 = k2 + kspan;
  2803. k4 = k3 + kspan;
  2804. akp = a[k1] + a[k4];
  2805. akm = a[k1] - a[k4];
  2806. bkp = b[k1] + b[k4];
  2807. bkm = b[k1] - b[k4];
  2808. ajp = a[k2] + a[k3];
  2809. ajm = a[k2] - a[k3];
  2810. bjp = b[k2] + b[k3];
  2811. bjm = b[k2] - b[k3];
  2812. aa = a[kk];
  2813. bb = b[kk];
  2814. a[kk] = (float)(aa + akp + ajp);
  2815. b[kk] = (float)(bb + bkp + bjp);
  2816. ak = (akp*c72) + (ajp*c2) + aa;
  2817. bk = (bkp*c72) + (bjp*c2) + bb;
  2818. aj = (akm*s72) + (ajm*s2);
  2819. bj = (bkm*s72) + (bjm*s2);
  2820. a[k1] = (float)(ak - bj);
  2821. a[k4] = (float)(ak + bj);
  2822. b[k1] = (float)(bk + aj);
  2823. b[k4] = (float)(bk - aj);
  2824. ak = (akp*c2) + (ajp*c72) + aa;
  2825. bk = (bkp*c2) + (bjp*c72) + bb;
  2826. aj = (akm*s2) - (ajm*s72);
  2827. bj = (bkm*s2) - (bjm*s72);
  2828. a[k2] = (float)(ak - bj);
  2829. a[k3] = (float)(ak + bj);
  2830. b[k2] = (float)(bk + aj);
  2831. b[k3] = (float)(bk - aj);
  2832. kk = k4 + kspan;
  2833. if(kk < nn) goto lbl220;
  2834. kk -= nn;
  2835. if(kk <= kspan) goto lbl220;
  2836. goto lbl290;
  2837. /*
  2838. * transform for odd factors
  2839. */
  2840. lbl230: k = nfac[i];
  2841. kspnn = kspan;
  2842. kspan /= k;
  2843. if(k==3) goto lbl100;
  2844. if(k==5) goto lbl210;
  2845. if(k==jf) goto lbl250;
  2846. jf = k;
  2847. s1 = rad/(((double)(k))/8.0);
  2848. c1 = cos(s1);
  2849. s1 = sin(s1);
  2850. ck[jf] = 1.0f;
  2851. sk[jf] = 0.0f;
  2852. for(j=1; j<k ; j++){
  2853. ck[j] = (float)((ck[k])*c1 + (sk[k])*s1);
  2854. sk[j] = (float)((ck[k])*s1 - (sk[k])*c1);
  2855. k--;
  2856. ck[k] = ck[j];
  2857. sk[k] = -(sk[j]);
  2858. }
  2859. lbl250: k1 = kk;
  2860. k2 = kk + kspnn;
  2861. aa = a[kk];
  2862. bb = b[kk];
  2863. ak = aa;
  2864. bk = bb;
  2865. j = 1;
  2866. k1 += kspan;
  2867. do{ k2 -= kspan;
  2868. j++;
  2869. at[j] = a[k1] + a[k2];
  2870. ak = at[j] + ak;
  2871. bt[j] = b[k1] + b[k2];
  2872. bk = bt[j] + bk;
  2873. j++;
  2874. at[j] = a[k1] - a[k2];
  2875. bt[j] = b[k1] - b[k2];
  2876. k1 += kspan;
  2877. }while(k1 < k2);
  2878. a[kk] = (float)ak;
  2879. b[kk] = (float)bk;
  2880. k1 = kk;
  2881. k2 = kk + kspnn;
  2882. j = 1;
  2883. lbl270: k1 += kspan;
  2884. k2 -= kspan;
  2885. jj = j;
  2886. ak = aa;
  2887. bk = bb;
  2888. aj = 0.0;
  2889. bj = 0.0;
  2890. k = 1;
  2891. do{ k++;
  2892. ak = (at[k] * ck[jj]) + ak;
  2893. bk = (bt[k] * ck[jj]) + bk;
  2894. k++;
  2895. aj = (at[k] * sk[jj]) + aj;
  2896. bj = (bt[k] * sk[jj]) + bj;
  2897. jj += j;
  2898. if (jj > jf)
  2899. jj -= jf;
  2900. }while(k < jf);
  2901. k = jf - j;
  2902. a[k1] = (float)(ak - bj);
  2903. b[k1] = (float)(bk + aj);
  2904. a[k2] = (float)(ak + bj);
  2905. b[k2] = (float)(bk - aj);
  2906. j++;
  2907. if(j < k) goto lbl270;
  2908. kk += kspnn;
  2909. if(kk <= nn) goto lbl250;
  2910. kk -= nn;
  2911. if(kk<=kspan) goto lbl250;
  2912. /*
  2913. * multiply by rotation factor (except for factors of 2 and 4)
  2914. */
  2915. lbl290: if(i==m) goto lbl350;
  2916. kk = jc + 1;
  2917. lbl300: c2 = 1.0 - cd;
  2918. s1 = sd;
  2919. mm = min( kspan, klim);
  2920. goto lbl320;
  2921. lbl310: c2 = c1 - ((cd*c1) + (sd*s1));
  2922. s1 = s1 + ((sd*c1) - (cd*s1));
  2923. lbl320: c1 = c2;
  2924. s2 = s1;
  2925. kk += kspan;
  2926. lbl330: ak = a[kk];
  2927. a[kk] = (float)((c2*ak) - (s2 * b[kk]));
  2928. b[kk] = (float)((s2*ak) + (c2 * b[kk]));
  2929. kk += kspnn;
  2930. if(kk <= nt) goto lbl330;
  2931. ak = s1*s2;
  2932. s2 = (s1*c2) + (c1*s2);
  2933. c2 = (c1*c2) - ak;
  2934. kk -= (nt - kspan);
  2935. if(kk <= kspnn) goto lbl330;
  2936. kk -= (kspnn - jc);
  2937. if(kk <= mm) goto lbl310;
  2938. if(kk < kspan) goto lbl340;
  2939. kk -= (kspan - jc - inc);
  2940. if(kk <= (jc+jc)) goto lbl300;
  2941. goto lbl40;
  2942. lbl340: s1 = ((double)((kk-1)/jc)) * dr * rad;
  2943. c2 = cos(s1);
  2944. s1 = sin(s1);
  2945. mm = min( kspan, mm+klim);
  2946. goto lbl320;
  2947. /*
  2948. * permute the results to normal order---done in two stages
  2949. * permutation for square factors of n
  2950. */
  2951. lbl350: np[1] = ks;
  2952. if (!(*kt)) goto lbl440;
  2953. k = *kt + *kt + 1;
  2954. if(m < k)
  2955. k--;
  2956. np[k+1] = jc;
  2957. for(j=1; j < k; j++,k--){
  2958. np[j+1] = np[j] / nfac[j];
  2959. np[k] = np[k+1] * nfac[j];
  2960. }
  2961. k3 = np[k+1];
  2962. kspan = np[2];
  2963. kk = jc + 1;
  2964. k2 = kspan + 1;
  2965. j = 1;
  2966. if(n != ntot) goto lbl400;
  2967. /*
  2968. * permutation for single-variate transform (optional code)
  2969. */
  2970. lbl370: do{ ak = a[kk];
  2971. a[kk] = a[k2];
  2972. a[k2] = (float)ak;
  2973. bk = b[kk];
  2974. b[kk] = b[k2];
  2975. b[k2] = (float)bk;
  2976. kk += inc;
  2977. k2 += kspan;
  2978. }while(k2 < ks);
  2979. lbl380: do{ k2 -= np[j++];
  2980. k2 += np[j+1];
  2981. }while(k2 > np[j]);
  2982. j = 1;
  2983. lbl390: if(kk < k2){
  2984. goto lbl370;
  2985. }
  2986. kk += inc;
  2987. k2 += kspan;
  2988. if(k2 < ks) goto lbl390;
  2989. if(kk < ks) goto lbl380;
  2990. jc = k3;
  2991. goto lbl440;
  2992. /*
  2993. * permutation for multivariate transform
  2994. */
  2995. lbl400: do{ do{ k = kk + jc;
  2996. do{ ak = a[kk];
  2997. a[kk] = a[k2];
  2998. a[k2] = (float)ak;
  2999. bk = b[kk];
  3000. b[kk] = b[k2];
  3001. b[k2] = (float)bk;
  3002. kk += inc;
  3003. k2 += inc;
  3004. }while(kk < k);
  3005. kk += (ks - jc);
  3006. k2 += (ks - jc);
  3007. }while(kk < nt);
  3008. k2 -= (nt - kspan);
  3009. kk -= (nt - jc);
  3010. }while(k2 < ks);
  3011. lbl420: do{ k2 -= np[j++];
  3012. k2 += np[j+1];
  3013. }while(k2 > np[j]);
  3014. j = 1;
  3015. lbl430: if(kk < k2) goto lbl400;
  3016. kk += jc;
  3017. k2 += kspan;
  3018. if(k2 < ks) goto lbl430;
  3019. if(kk < ks) goto lbl420;
  3020. jc = k3;
  3021. lbl440: if((2*(*kt))+1 >= m)
  3022. return(FINISHED);
  3023. kspnn = *(np + *(kt) + 1);
  3024. j = m - *kt;
  3025. nfac[j+1] = 1;
  3026. lbl450: nfac[j] = nfac[j] * nfac[j+1];
  3027. j--;
  3028. if(j != *kt) goto lbl450;
  3029. *kt = *(kt) + 1;
  3030. nn = nfac[*kt] - 1;
  3031. jj = 0;
  3032. j = 0;
  3033. goto lbl480;
  3034. lbl460: jj -= k2;
  3035. k2 = kk;
  3036. kk = nfac[++k];
  3037. lbl470: jj += kk;
  3038. if(jj >= k2) goto lbl460;
  3039. np[j] = jj;
  3040. lbl480: k2 = nfac[*kt];
  3041. k = *kt + 1;
  3042. kk = nfac[k];
  3043. j++;
  3044. if(j <= nn) goto lbl470;
  3045. /* Determine permutation cycles of length greater than 1 */
  3046. j = 0;
  3047. goto lbl500;
  3048. lbl490: k = kk;
  3049. kk = np[k];
  3050. np[k] = -kk;
  3051. if(kk != j) goto lbl490;
  3052. k3 = kk;
  3053. lbl500: kk = np[++j];
  3054. if(kk < 0) goto lbl500;
  3055. if(kk != j) goto lbl490;
  3056. np[j] = -j;
  3057. if(j != nn) goto lbl500;
  3058. maxf *= inc;
  3059. /* Perform reordering following permutation cycles */
  3060. goto lbl570;
  3061. lbl510: j--;
  3062. if (np[j] < 0) goto lbl510;
  3063. jj = jc;
  3064. lbl520: kspan = jj;
  3065. if(jj > maxf)
  3066. kspan = maxf;
  3067. jj -= kspan;
  3068. k = np[j];
  3069. kk = (jc*k) + i + jj;
  3070. k1 = kk + kspan;
  3071. k2 = 0;
  3072. lbl530: k2++;
  3073. at[k2] = a[k1];
  3074. bt[k2] = b[k1];
  3075. k1 -= inc;
  3076. if(k1 != kk) goto lbl530;
  3077. lbl540: k1 = kk + kspan;
  3078. k2 = k1 - (jc * (k + np[k]));
  3079. k = -(np[k]);
  3080. lbl550: a[k1] = a[k2];
  3081. b[k1] = b[k2];
  3082. k1 -= inc;
  3083. k2 -= inc;
  3084. if(k1 != kk) goto lbl550;
  3085. kk = k2;
  3086. if(k != j) goto lbl540;
  3087. k1 = kk + kspan;
  3088. k2 = 0;
  3089. lbl560: k2++;
  3090. a[k1] = at[k2];
  3091. b[k1] = bt[k2];
  3092. k1 -= inc;
  3093. if(k1 != kk) goto lbl560;
  3094. if(jj) goto lbl520;
  3095. if(j != 1) goto lbl510;
  3096. lbl570: j = k3 + 1;
  3097. nt -= kspnn;
  3098. i = nt - inc + 1;
  3099. if(nt >= 0) goto lbl510;
  3100. return(FINISHED);;
  3101. }
  3102. /*
  3103. *-----------------------------------------------------------------------
  3104. * subroutine: reals
  3105. * used with 'fft' to compute fourier transform or inverse for real data
  3106. *-----------------------------------------------------------------------
  3107. * this is the call from C:
  3108. * reals_(anal,banal,N2,mtwo);
  3109. * which has been changed from CARL call
  3110. * reals_(anal,banal,&N2,&mtwo);
  3111. */
  3112. int reals_(float *a, float *b, int n, int isn)
  3113. /* a refers to an array of floats 'anal' */
  3114. /* b refers to an array of floats 'banal' */
  3115. /* See IEEE book for a long comment here on usage */
  3116. { int inc,
  3117. j,
  3118. k,
  3119. lim,
  3120. mm,ml,
  3121. nf,nk,nh;
  3122. double aa,ab,
  3123. ba,bb,
  3124. cd,cn,
  3125. dr,
  3126. em,
  3127. rad,re,
  3128. sd,sn;
  3129. double xx; /******* ADDED APRIL 1991 ******/
  3130. /* adjust input array pointers (called from C) */
  3131. a--; b--;
  3132. inc=abs(isn);
  3133. nf=abs(n);
  3134. if(nf*isn==0){
  3135. sprintf(errstr,"zero in reals parameters in FFT : %d : %d ",n,isn);
  3136. return(DATA_ERROR);;
  3137. }
  3138. nk = (nf*inc) + 2;
  3139. nh = nk/2;
  3140. /*****************************
  3141. rad = atan((double)1.0);
  3142. ******************************/
  3143. rad = 0.785398163397448278900;
  3144. dr = -4.0/(double)(nf);
  3145. /********************************** POW2 REMOVED APRIL 1991 *****************
  3146. cd = 2.0 * (pow2(sin((double)0.5 * dr * rad)));
  3147. *****************************************************************************/
  3148. xx = sin((double)0.5 * dr * rad);
  3149. cd = 2.0 * xx * xx;
  3150. sd = sin(dr * rad);
  3151. /*
  3152. * sin,cos values are re-initialized each lim steps
  3153. */
  3154. lim = 32;
  3155. mm = lim;
  3156. ml = 0;
  3157. sn = 0.0;
  3158. if(isn<0){
  3159. cn = 1.0;
  3160. a[nk-1] = a[1];
  3161. b[nk-1] = b[1]; }
  3162. else {
  3163. cn = -1.0;
  3164. sd = -sd;
  3165. }
  3166. for(j=1;j<=nh;j+=inc) {
  3167. k = nk - j;
  3168. aa = a[j] + a[k];
  3169. ab = a[j] - a[k];
  3170. ba = b[j] + b[k];
  3171. bb = b[j] - b[k];
  3172. re = (cn*ba) + (sn*ab);
  3173. em = (sn*ba) - (cn*ab);
  3174. b[k] = (float)((em-bb)*0.5);
  3175. b[j] = (float)((em+bb)*0.5);
  3176. a[k] = (float)((aa-re)*0.5);
  3177. a[j] = (float)((aa+re)*0.5);
  3178. ml++;
  3179. if(ml!=mm){
  3180. aa = cn - ((cd*cn)+(sd*sn));
  3181. sn = ((sd*cn) - (cd*sn)) + sn;
  3182. cn = aa;}
  3183. else {
  3184. mm +=lim;
  3185. sn = ((float)ml) * dr * rad;
  3186. cn = cos(sn);
  3187. if(isn>0)
  3188. cn = -cn;
  3189. sn = sin(sn);
  3190. }
  3191. }
  3192. return(FINISHED);
  3193. }
  3194. /************************ SA_INITIALISE_SPECENV ************************/
  3195. int sa_initialise_specenv(dataptr dz)
  3196. {
  3197. int arraycnt;
  3198. dz->clength = dz->wanted/2;
  3199. dz->nyquist = dz->infile->srate/2.0;
  3200. dz->chwidth = dz->nyquist/(double)(dz->iparam[SA_CHANS] / 2);
  3201. arraycnt = dz->clength + 1;
  3202. if((dz->specenvfrq = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
  3203. sprintf(errstr,"INSUFFICIENT MEMORY for formant frq array.\n");
  3204. return(MEMORY_ERROR);
  3205. }
  3206. if((dz->specenvpch = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
  3207. sprintf(errstr,"INSUFFICIENT MEMORY for formant pitch array.\n");
  3208. return(MEMORY_ERROR);
  3209. }
  3210. /*RWD zero the data */
  3211. memset(dz->specenvpch,0,arraycnt * sizeof(float));
  3212. if((dz->specenvamp = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
  3213. sprintf(errstr,"INSUFFICIENT MEMORY for formant aplitude array.\n");
  3214. return(MEMORY_ERROR);
  3215. }
  3216. if((dz->specenvtop = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
  3217. sprintf(errstr,"INSUFFICIENT MEMORY for formant frq limit array.\n");
  3218. return(MEMORY_ERROR);
  3219. }
  3220. return(FINISHED);
  3221. }
  3222. /************************ SA_SET_SPECENV_FRQS ************************
  3223. *
  3224. * FREQWISE BANDS = number of channels for each specenv point
  3225. * PICHWISE BANDS = number of points per octave
  3226. */
  3227. int sa_set_specenv_frqs(dataptr dz)
  3228. {
  3229. int exit_status;
  3230. int arraycnt;
  3231. double bandbot;
  3232. double *interval;
  3233. int m, n, k = 0, cc;
  3234. arraycnt = dz->clength + 1;
  3235. if((exit_status = sa_setup_octaveband_steps(&interval,dz))<0)
  3236. return(exit_status);
  3237. if((exit_status = sa_setup_low_octave_bands(arraycnt,dz))<0)
  3238. return(exit_status);
  3239. k = TOP_OF_LOW_OCTAVE_BANDS;
  3240. cc = CHAN_ABOVE_LOW_OCTAVES;
  3241. while(cc <= dz->clength) {
  3242. m = 0;
  3243. if((bandbot = dz->chwidth * (double)cc) >= dz->nyquist)
  3244. break;
  3245. for(n=0;n<dz->iparam[SA_FORMANT_BANDS];n++) {
  3246. if(k >= arraycnt) {
  3247. sprintf(errstr,"Formant array too small: sa_set_specenv_frqs()\n");
  3248. return(PROGRAM_ERROR);
  3249. }
  3250. dz->specenvfrq[k] = (float)(bandbot * interval[m++]);
  3251. dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
  3252. dz->specenvtop[k++] = (float)(bandbot * interval[m++]);
  3253. }
  3254. cc *= 2; /* 8-16: 16-32: 32-64 etc as 8vas, then split into bands */
  3255. }
  3256. dz->specenvfrq[k] = (float)dz->nyquist;
  3257. dz->specenvpch[k] = (float)log10(dz->nyquist);
  3258. dz->specenvtop[k] = (float)dz->nyquist;
  3259. dz->specenvamp[k] = (float)0.0;
  3260. k++;
  3261. dz->infile->specenvcnt = k;
  3262. return(FINISHED);
  3263. }
  3264. /************************* SA_SETUP_OCTAVEBAND_STEPS ************************/
  3265. int sa_setup_octaveband_steps(double **interval,dataptr dz)
  3266. {
  3267. double octave_step;
  3268. int n = 1, m = 0, halfbands_per_octave = dz->iparam[SA_FORMANT_BANDS] * 2;
  3269. if((*interval = (double *)malloc(halfbands_per_octave * sizeof(double)))==NULL) {
  3270. sprintf(errstr,"INSUFFICIENT MEMORY establishing interval array for formants.\n");
  3271. return(MEMORY_ERROR);
  3272. }
  3273. while(n < halfbands_per_octave) {
  3274. octave_step = (double)n++/(double)halfbands_per_octave;
  3275. (*interval)[m++] = pow(2.0,octave_step);
  3276. }
  3277. (*interval)[m] = 2.0;
  3278. return(FINISHED);
  3279. }
  3280. /************************ SA_SETUP_LOW_OCTAVE_BANDS ***********************
  3281. *
  3282. * Lowest PVOC channels span larger freq steps and therefore we must
  3283. * group them in octave bands, rather than in anything smaller.
  3284. */
  3285. int sa_setup_low_octave_bands(int arraycnt,dataptr dz)
  3286. {
  3287. int n;
  3288. arraycnt = dz->clength + 1;
  3289. if(arraycnt < LOW_OCTAVE_BANDS) {
  3290. sprintf(errstr,"Insufficient array space for low_octave_bands\n");
  3291. return(PROGRAM_ERROR);
  3292. }
  3293. for(n=0;n<LOW_OCTAVE_BANDS;n++) {
  3294. switch(n) {
  3295. case(0):
  3296. dz->specenvfrq[0] = (float)1.0; /* frq whose log is 0 */
  3297. dz->specenvpch[0] = (float)0.0;
  3298. dz->specenvtop[0] = (float)dz->chwidth; /* 8VA wide bands */
  3299. break;
  3300. case(1):
  3301. dz->specenvfrq[1] = (float)(dz->chwidth * 1.5); /* Centre Chs 1-2 */
  3302. dz->specenvpch[1] = (float)log10(dz->specenvfrq[1]);
  3303. dz->specenvtop[1] = (float)(dz->chwidth * 2.0);
  3304. break;
  3305. case(2):
  3306. dz->specenvfrq[2] = (float)(dz->chwidth * 3.0); /* Centre Chs 2-4 */
  3307. dz->specenvpch[2] = (float)log10(dz->specenvfrq[2]);
  3308. dz->specenvtop[2] = (float)(dz->chwidth * 4.0);
  3309. break;
  3310. case(3):
  3311. dz->specenvfrq[3] = (float)(dz->chwidth * 6.0); /* Centre Chs 4-8 */
  3312. dz->specenvpch[3] = (float)log10(dz->specenvfrq[3]);
  3313. dz->specenvtop[3] = (float)(dz->chwidth * 8.0);
  3314. break;
  3315. default:
  3316. sprintf(errstr,"Insufficient low octave band setups in sa_setup_low_octave_bands()\n");
  3317. return(PROGRAM_ERROR);
  3318. }
  3319. }
  3320. return(FINISHED);
  3321. }
  3322. /********************** SA_EXTRACT_SPECENV *******************/
  3323. int sa_extract_specenv(float *anal,dataptr dz)
  3324. {
  3325. int n, cc, vc, specenvcnt_less_one;
  3326. int botchan, topchan;
  3327. double botfreq, topfreq;
  3328. double bwidth_in_chans;
  3329. float *ampstore;
  3330. ampstore = dz->specenvamp;
  3331. specenvcnt_less_one = dz->infile->specenvcnt - 1;
  3332. vc = 0;
  3333. for(n=0;n<dz->infile->specenvcnt;n++)
  3334. ampstore[n] = (float)0.0;
  3335. topfreq = 0.0f;
  3336. n = 0;
  3337. while(n < specenvcnt_less_one) {
  3338. botfreq = topfreq;
  3339. botchan = (int)((botfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  3340. botchan -= CHAN_SRCHRANGE_F;
  3341. botchan = max(botchan,0);
  3342. topfreq = dz->specenvtop[n];
  3343. topchan = (int)((topfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  3344. topchan += CHAN_SRCHRANGE_F;
  3345. topchan = min(topchan,dz->clength);
  3346. for(cc = botchan,vc = botchan * 2; cc < topchan; cc++,vc += 2) {
  3347. if(anal[FREQ] < 0.0) // rectify if ness
  3348. anal[FREQ] = (float)-anal[FREQ];
  3349. if(anal[FREQ] >= botfreq && anal[FREQ] < topfreq)
  3350. ampstore[n] = (float)(ampstore[n] + anal[AMPP]);
  3351. }
  3352. bwidth_in_chans = (double)(topfreq - botfreq)/dz->chwidth;
  3353. ampstore[n] = (float)(ampstore[n]/bwidth_in_chans);
  3354. n++;
  3355. }
  3356. return(FINISHED);
  3357. }
  3358. /**************************** IS_A_HARMONIC_X *************************/
  3359. int is_a_harmonic_x(double frq1,double fundamental)
  3360. {
  3361. double ratio;
  3362. int iratio, hcnt;
  3363. double intvl, harmonicfrq;
  3364. harmonicfrq = fundamental;
  3365. hcnt = 1;
  3366. while(harmonicfrq < frq1 * SEMITONE_INTERVAL) {
  3367. ratio = frq1/harmonicfrq;
  3368. iratio = round(ratio);
  3369. if(iratio != 1) {
  3370. if(ratio > iratio)
  3371. intvl = ratio/(double)iratio;
  3372. else
  3373. intvl = (double)iratio/ratio;
  3374. if(intvl < quartertone)
  3375. return(TRUE);
  3376. }
  3377. hcnt++;
  3378. harmonicfrq = fundamental * hcnt;
  3379. }
  3380. return(FALSE);
  3381. }
  3382. /******************************** EXTRACT_ENV_FROM_SNDFILE *****************************/
  3383. int extract_env_from_sndfile(dataptr dz)
  3384. {
  3385. int n, i;
  3386. float *buffer = dz->sampbuf[0];
  3387. double thismaxsamp, thisval;
  3388. for(n = 0; n < dz->envcnt; n++) {
  3389. if((dz->ssampsread = fgetfbufEx(buffer, dz->iparam[SA_TSTEP],dz->ifd[0],0)) < 0) {
  3390. sprintf(errstr,"Can't read samples from soundfile: to extract envelope.\n");
  3391. return(SYSTEM_ERROR);
  3392. }
  3393. thismaxsamp = 0.0;
  3394. for(i = 0; i<dz->ssampsread; i++) {
  3395. if((thisval = fabs(buffer[i]))>thismaxsamp)
  3396. thismaxsamp = thisval;
  3397. }
  3398. dz->env[n] = (float)thismaxsamp;
  3399. }
  3400. // NORMALISE
  3401. thismaxsamp = -HUGE;
  3402. for(n = 0; n < dz->envcnt; n++)
  3403. thismaxsamp = max(thismaxsamp,dz->env[n]);
  3404. if(thismaxsamp <= 0.0) {
  3405. sprintf(errstr,"No significant level found in source sound.\n");
  3406. return DATA_ERROR;
  3407. }
  3408. for(n = 0; n < dz->envcnt; n++)
  3409. dz->env[n] = (float)(dz->env[n]/thismaxsamp);
  3410. memset((char *)buffer,0,(dz->iparam[SA_TSTEP] * 2) * sizeof(float));
  3411. sndseekEx(dz->ifd[0],0,0);
  3412. return(FINISHED);
  3413. }
  3414. /******************************************* GET_TEMPERED_PITCH ********************************/
  3415. int get_tempered_pitch(float *averages, float *averages2, float *averages3, dataptr dz)
  3416. {
  3417. double maxval;
  3418. int maxpos;
  3419. int *pitches = dz->iparray[0];
  3420. int jj, kk;
  3421. if(dz->pitchcnt != 0) {
  3422. for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
  3423. averages3[kk] = averages[kk] + averages2[kk]; // sum average levels from last 2 groups
  3424. maxval = -10000;
  3425. maxpos = 0;
  3426. // For every semitone bin // Find loudest frq
  3427. for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2) {
  3428. if(averages3[kk] > maxval) { // is it the loudest
  3429. maxval = averages3[kk];
  3430. maxpos = jj;
  3431. }
  3432. }
  3433. pitches[dz->pitchcnt] = maxpos - 1; // assign pitch (MIDI bins start at midi = -1 : so bin2 is midi=1)
  3434. }
  3435. memcpy((char *)averages2,(char *)averages,(BINCNT *2) * sizeof(float));
  3436. for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
  3437. averages[kk] = 0.0;
  3438. dz->pitchcnt++;
  3439. return FINISHED;
  3440. }
  3441. /******************************************* GET_TEMPERED_HF ********************************/
  3442. int get_tempered_hf(float *averages, float *averages2, float *averages3, dataptr dz)
  3443. {
  3444. double maxval;
  3445. int maxpos;
  3446. int jj, kk, mm;
  3447. if(dz->pitchcnt != 0) {
  3448. for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
  3449. averages3[kk] = averages[kk] + averages2[kk]; // sum average levels from last 2 groups
  3450. for(mm = 0; mm < 8;mm++) { // Get the 8 loudest peaks, in loudness order
  3451. maxval = -10000;
  3452. maxpos = 0;
  3453. // For every semitone bin // Find loudest frq
  3454. for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2) {
  3455. if(averages3[kk] > maxval) { // is it the loudest
  3456. maxval = averages3[kk];
  3457. maxpos = jj;
  3458. }
  3459. }
  3460. dz->iparray[mm][dz->pitchcnt] = maxpos - 1; // assign pitch (MIDI bins start at midi = -1 : so bin2 is midi=1)
  3461. kk = (maxpos * 2) + 1;
  3462. averages3[kk] = -10000; // set the current loudest bin to a -ve val, so it is ignored in next pass of mm loop
  3463. }
  3464. }
  3465. memcpy((char *)averages2,(char *)averages,(BINCNT *2) * sizeof(float));
  3466. for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
  3467. averages[kk] = 0.0;
  3468. dz->pitchcnt++;
  3469. return FINISHED;
  3470. }
  3471. /******************************************* SMOOTH_AND_OUTPUT_TEMPERED_PITCH ********************************/
  3472. int smooth_and_output_tempered_pitch(dataptr dz)
  3473. {
  3474. int n, m, t, k;
  3475. int *pitches = dz->iparray[0], lastpitch, thispitch, pitchrepet;
  3476. double *pichout = dz->parray[0], transittime;
  3477. /* Put times into array */
  3478. for(n=1, t = 2, m = 3;n < dz->envcnt; n++,t+=2,m+=2) {
  3479. pichout[t] = dz->param[SA_TSTEP] * n; // Time
  3480. pichout[m] = pitches[n]; // Pitch
  3481. }
  3482. for(n=1,m=2;n<dz->envcnt;n++,m+=2) {
  3483. if(dz->env[n] < dz->param[SA_GATE]) // Mark for deletion, pitches found at below gate-level
  3484. pichout[m] = -1.0;
  3485. if(pichout[m] >= 0.0) {
  3486. if((int)round(pichout[m+1]) < dz->param[SA_BOTRANGE])
  3487. pichout[m] = -1; // Mark for deletion, pitches below acceptable range
  3488. else if((int)round(pichout[m+1]) > dz->param[SA_TOPRANGE])
  3489. pichout[m] = -1; // Mark for deletion, pitches below acceptable range
  3490. }
  3491. }
  3492. n = 1;
  3493. m = 2;
  3494. while(n<dz->envcnt-1) {
  3495. if(pichout[m] < 0.0) {
  3496. for(k = m+2; k < dz->envcnt*2; k++) // Shuffle-down overwrite
  3497. pichout[k-2] = pichout[k];
  3498. dz->envcnt--;
  3499. } else {
  3500. n++;
  3501. m += 2;
  3502. }
  3503. }
  3504. if(pichout[m] < 0.0)
  3505. dz->envcnt--;
  3506. for(n=1,m=2;n<dz->envcnt;n++,m+=2) {
  3507. if(flteq(pichout[m+1],pichout[m-1])) // Mark for deletion, pitches that duplicate the previous pitch
  3508. pichout[m] = -1;
  3509. }
  3510. n = 1;
  3511. m = 2;
  3512. while(n<dz->envcnt-1) {
  3513. if(pichout[m] < 0.0) {
  3514. for(k = m+2; k < dz->envcnt*2; k++) // Shuffle-down overwrite
  3515. pichout[k-2] = pichout[k];
  3516. dz->envcnt--;
  3517. } else {
  3518. n++;
  3519. m += 2;
  3520. }
  3521. }
  3522. if(pichout[m] < 0.0)
  3523. dz->envcnt--;
  3524. if(dz->envcnt == 0) {
  3525. sprintf(errstr,"NO PITCHES FOUND\n");
  3526. return DATA_ERROR;
  3527. }
  3528. pichout[0] = 0.0; // Force a value at time zero
  3529. pichout[1] = pichout[3];
  3530. // Reduce data (where pitch is repeated)
  3531. lastpitch = (int)round(pichout[1]);
  3532. pitchrepet = 0;
  3533. for(n = 1;n< dz->envcnt;n++) {
  3534. k = n * 2; // time-index in output array
  3535. m = k+1; // pitch-index in output array
  3536. thispitch = (int)round(pichout[m]);
  3537. if(thispitch == lastpitch)
  3538. pitchrepet++;
  3539. else {
  3540. if(pitchrepet) { // If a pitch repeats
  3541. k = n; // Copy pitches down over eliminated pitches
  3542. m = n - pitchrepet;
  3543. k = k * 2;
  3544. m = m * 2;
  3545. while(k < dz->envcnt * 2)
  3546. pichout[m++] = pichout[k++];
  3547. dz->envcnt -= pitchrepet;
  3548. n -= pitchrepet;
  3549. }
  3550. lastpitch = thispitch;
  3551. pitchrepet = 0;
  3552. }
  3553. }
  3554. for(n = 0,m=0;n< dz->envcnt;n++,m+=2) {
  3555. fprintf(dz->fp,"%f\t%d\t1\n",pichout[m],(int)round(pichout[m+1]));
  3556. if(n < dz->envcnt-1) {
  3557. transittime = min(SA_TRANSIT,(pichout[m+2] - pichout[m])/2.0);
  3558. fprintf(dz->fp,"%f\t%d\t1\n",pichout[m+2] - transittime,(int)round(pichout[m+1]));
  3559. } else
  3560. fprintf(dz->fp,"10000\t%d\t1\n",(int)round(pichout[m+1]));
  3561. }
  3562. return FINISHED;
  3563. }
  3564. /******************************************* SMOOTH_AND_OUTPUT_VARYING_HF ********************************/
  3565. int smooth_and_output_varying_hf(dataptr dz)
  3566. {
  3567. int exit_status, reranged[8], lastpitch[8], thispitch[8], does_repeat;
  3568. int n, m, t, k, f, omitsum = 0, hfrepet;
  3569. int itemp, peakcnt, omit[8];
  3570. double transittime, temp;
  3571. char tempstr[4000], tempstr2[4000];
  3572. int downtranspos = 0;
  3573. /* Eliminate harmonics of lower peaks */
  3574. if(dz->iparam[SA_PKCNT] < 8) {
  3575. for(n=1;n < dz->envcnt; n++) { /* Initially, arrays 0-7 run from loudest to quietest pitch */
  3576. for(m=0,k = 7;m<4;m++,k--) { /* invert order of array pitches at time 'n', so they run from quietest to loudest */
  3577. itemp = dz->iparray[m][n];
  3578. dz->iparray[m][n] = dz->iparray[k][n];
  3579. dz->iparray[k][n] = itemp;
  3580. }
  3581. peakcnt = 8;
  3582. for(m=0;m<8;m++) {
  3583. if(dz->iparray[m][n] < 0) // skip arrays that have already been eliminated from search
  3584. continue;
  3585. for(t=0;t<peakcnt;t++) { // Compare each peak pitch with all others
  3586. if(t==m) // except itself
  3587. continue;
  3588. if(dz->iparray[t][n] < 0) // skip arrays that have already been eliminated from search
  3589. continue;
  3590. // If one partial is a harmonic of another, mark it for elimination
  3591. if(dz->iparray[m][n] == dz->iparray[t][n] + 12 || dz->iparray[m][n] == dz->iparray[t][n] + 19 || dz->iparray[m][n] == dz->iparray[t][n] + 24) {
  3592. dz->iparray[m][n] = -1;
  3593. peakcnt--; // count remaining peaks
  3594. break; // and abandon comparison with other peaks
  3595. }
  3596. }
  3597. if(peakcnt <= dz->iparam[SA_PKCNT])// if only the required no of peaks remains, stop
  3598. break;
  3599. }
  3600. for(m=0,k = 7;m<4;m++,k--) { /* invert order of array pitches at time 'n', so loudest is below quietest */
  3601. itemp = dz->iparray[m][n];
  3602. dz->iparray[m][n] = dz->iparray[k][n];
  3603. dz->iparray[k][n] = itemp;
  3604. }
  3605. k = 0; // Move SA_PKCNT valid peaks to topmost arrays 0 to SA_PKCNT-1
  3606. for(m=0;m<8;m++) {
  3607. if(dz->iparray[m][n] >= 0) {
  3608. if(k!=m) // Move item up arrays only if ness
  3609. dz->iparray[k][n] = dz->iparray[m][n];
  3610. k++;
  3611. if(k >= dz->iparam[SA_PKCNT])
  3612. break;
  3613. }
  3614. }
  3615. }
  3616. }
  3617. /* Put times into arrays */
  3618. for(n=1, t = 2, m = 3;n < dz->envcnt; n++,t+=2,m+=2) {
  3619. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3620. dz->parray[k][t] = dz->param[SA_TSTEP] * n; // Time
  3621. dz->parray[k][m] = (double)dz->iparray[k][n]; // Pitch
  3622. }
  3623. }
  3624. for(n=1,t=2;n<dz->envcnt;n++,t+=2) {
  3625. if(dz->env[n] < dz->param[SA_GATE]) // Mark for deletion, pitches found where sound is below gate-level
  3626. dz->parray[0][t] = -1.0;
  3627. }
  3628. n = 1;
  3629. m = 2;
  3630. while(n<dz->envcnt-1) {
  3631. if(dz->parray[0][m] < 0.0) {
  3632. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3633. for(t = m+2; t < dz->envcnt*2; t++) // Shuffle-down overwrite
  3634. dz->parray[k][t-2] = dz->parray[k][t];
  3635. }
  3636. dz->envcnt--;
  3637. } else {
  3638. n++;
  3639. m += 2;
  3640. }
  3641. }
  3642. if(dz->parray[0][m] < 0.0)
  3643. dz->envcnt--;
  3644. if(dz->envcnt == 0) {
  3645. sprintf(errstr,"NO PITCHES FOUND\n");
  3646. return DATA_ERROR;
  3647. }
  3648. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3649. dz->parray[k][0] = 0.0; // Force a value at time zero
  3650. dz->parray[k][1] = dz->parray[k][3];
  3651. }
  3652. // Force pitches, at each time 'n', into ascending order
  3653. for(n=0,f=1;n<dz->envcnt;n++,f+=2) {
  3654. for(k=0;k<dz->iparam[SA_PKCNT]-1;k++) {
  3655. for(m=k+1;m<dz->iparam[SA_PKCNT];m++) {
  3656. if(dz->parray[m][f] < dz->parray[k][f]) {
  3657. temp = dz->parray[k][f];
  3658. dz->parray[k][f] = dz->parray[m][f];
  3659. dz->parray[m][f] = temp;
  3660. }
  3661. }
  3662. }
  3663. }
  3664. // If any filter strand is everywhere out of range, mark it for elimination
  3665. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3666. omit[k] = 1;
  3667. for(n=0,f=1;n<dz->envcnt;n++,f+=2) {
  3668. if(dz->parray[k][f] >= dz->param[SA_BOTRANGE] && dz->parray[k][f] <= dz->param[SA_TOPRANGE]) {
  3669. omit[k] = 0;
  3670. break;
  3671. }
  3672. }
  3673. }
  3674. // Delete out-of-range threads by shuffle-down overwrite
  3675. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3676. if(omit[k]) {
  3677. omitsum++;
  3678. if(k < dz->iparam[SA_PKCNT] - 1) {
  3679. for(m=k+1;m<dz->iparam[SA_PKCNT];m++)
  3680. dz->parray[m-1] = dz->parray[m];
  3681. }
  3682. if(--(dz->iparam[SA_PKCNT]) <= 0) {
  3683. sprintf(errstr,"ALL EXTRACTED HARMONIC FIELD COMPONENTS ARE OUT OF RANGE.\n");
  3684. return DATA_ERROR;
  3685. }
  3686. }
  3687. }
  3688. if(omitsum) {
  3689. if(omitsum == 1)
  3690. fprintf(stdout,"WARNING: 1 PEAK-STRAND ENTIRELY OUT OF RANGE. REDUCED PEAK-COUNT TO %d\n",dz->iparam[SA_PKCNT]);
  3691. else
  3692. fprintf(stdout,"WARNING: %d PEAK-STRANDS ARE ENTIRELY OUT OF RANGE. REDUCED PEAK-COUNT TO %d\n",omitsum,dz->iparam[SA_PKCNT]);
  3693. fflush(stdout);
  3694. }
  3695. // Data-reduce (remove repeating filters)
  3696. for(t = 0;t < dz->iparam[SA_PKCNT];t++)
  3697. lastpitch[t] = (int)round(dz->parray[t][1]);
  3698. hfrepet = 0;
  3699. for(n = 1;n< dz->envcnt;n++) {
  3700. k = n * 2; // time-index in output arrays
  3701. m = k+1; // pitch-index in output arrays
  3702. does_repeat = 1;
  3703. for(t = 0;t < dz->iparam[SA_PKCNT];t++) {
  3704. thispitch[t] = (int)round(dz->parray[t][m]);
  3705. if(thispitch[t] != lastpitch[t]) { // If this and lasttime pitches are NOT the same
  3706. // if both are out of range, both are zeroed in the output, so in effect equivalent
  3707. if((thispitch[t] < dz->param[SA_BOTRANGE] || thispitch[t] > dz->param[SA_TOPRANGE])
  3708. && (lastpitch[t] < dz->param[SA_BOTRANGE] || lastpitch[t] > dz->param[SA_TOPRANGE]))
  3709. continue;
  3710. does_repeat = 0; // Otherwise, pitches not the same, so HF not repeated.
  3711. break;
  3712. }
  3713. }
  3714. if(does_repeat)
  3715. hfrepet++;
  3716. else {
  3717. if(hfrepet) { // If an HF repeats
  3718. k = n; // Copy all HF pitches down over eliminated pitches
  3719. m = k - hfrepet;
  3720. k = k * 2;
  3721. m = m * 2;
  3722. while(k < dz->envcnt * 2) {
  3723. for(t = 0;t < dz->iparam[SA_PKCNT];t++)
  3724. dz->parray[t][m] = dz->parray[t][k];
  3725. k++;
  3726. m++;
  3727. }
  3728. dz->envcnt -= hfrepet;
  3729. n -= hfrepet;
  3730. }
  3731. for(t = 0;t < dz->iparam[SA_PKCNT];t++)
  3732. lastpitch[t] = thispitch[t];
  3733. hfrepet = 0;
  3734. }
  3735. }
  3736. // Attempt downward octave transpos, if flagged
  3737. if(dz->vflag[SA_DOWNOCT]) {
  3738. downtranspos = 1;
  3739. for(n = 0,t=1;n < dz->envcnt;n++,t+=2) {
  3740. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3741. if(dz->parray[0][m+1] - 12.0 < 0) {
  3742. downtranspos = 0;
  3743. break;
  3744. }
  3745. }
  3746. if(k<dz->iparam[SA_PKCNT])
  3747. break;
  3748. }
  3749. if(!downtranspos) {
  3750. fprintf(stdout,"WARNING: OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
  3751. fflush(stdout);
  3752. }
  3753. } else if(dz->vflag[SA_DOWN2OCT]) {
  3754. downtranspos = 2;
  3755. for(n = 0,t=1;n < dz->envcnt;n++,t+=2) {
  3756. for(k=0;k<dz->iparam[SA_PKCNT];k++) {
  3757. if(dz->parray[0][m+1] - 24.0 < 0) {
  3758. downtranspos = 0;
  3759. break;
  3760. }
  3761. }
  3762. if(k<dz->iparam[SA_PKCNT])
  3763. break;
  3764. }
  3765. if(!downtranspos) {
  3766. fprintf(stdout,"WARNING: TWO OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
  3767. fflush(stdout);
  3768. }
  3769. }
  3770. // Print to output, zeroing any out-of-range pitches
  3771. for(n = 0,m=0;n < dz->envcnt;n++,m+=2) {
  3772. reranged[0] = 0;
  3773. if(dz->parray[0][m+1] < dz->param[SA_BOTRANGE] || dz->parray[0][m+1] > dz->param[SA_TOPRANGE]) {
  3774. // FORCE ELEMENT TO BE IN RANGE, BUT ZERO IT
  3775. if((exit_status = rerange_outofrange_pitch(0,n,dz))<0)
  3776. return exit_status;
  3777. reranged[0] = 1;
  3778. if(downtranspos)
  3779. dz->parray[0][m+1] -= (12.0 * downtranspos);
  3780. sprintf(tempstr,"%f\t%d\t0",dz->parray[0][m],(int)round(dz->parray[0][m+1]));
  3781. } else {
  3782. if(downtranspos)
  3783. dz->parray[0][m+1] -= 12.0;
  3784. sprintf(tempstr,"%f\t%d\t1",dz->parray[0][m],(int)round(dz->parray[0][m+1]));
  3785. }
  3786. for(k=1;k<dz->iparam[SA_PKCNT];k++) {
  3787. reranged[k] = 0;
  3788. if(dz->parray[k][m+1] < dz->param[SA_BOTRANGE] || dz->parray[k][m+1] > dz->param[SA_TOPRANGE]) {
  3789. if((exit_status = rerange_outofrange_pitch(k,n,dz))<0)
  3790. return exit_status;
  3791. reranged[k] = 1;
  3792. if(downtranspos)
  3793. dz->parray[k][m+1] -= 12.0;
  3794. sprintf(tempstr2,"\t%d\t0",(int)round(dz->parray[k][m+1]));
  3795. } else {
  3796. if(downtranspos)
  3797. dz->parray[k][m+1] -= 12.0;
  3798. sprintf(tempstr2,"\t%d\t1",(int)round(dz->parray[k][m+1]));
  3799. }
  3800. strcat(tempstr,tempstr2);
  3801. }
  3802. fprintf(dz->fp,"%s\n",tempstr);
  3803. if(n < dz->envcnt-1) {
  3804. transittime = min(SA_TRANSIT,(dz->parray[0][m+2] - dz->parray[0][m])/2.0);
  3805. if(reranged[0])
  3806. sprintf(tempstr,"%f\t%d\t0",dz->parray[0][m+2] - transittime,(int)round(dz->parray[0][m+1]));
  3807. else
  3808. sprintf(tempstr,"%f\t%d\t1",dz->parray[0][m+2] - transittime,(int)round(dz->parray[0][m+1]));
  3809. for(k=1;k<dz->iparam[SA_PKCNT];k++) {
  3810. if(reranged[k])
  3811. sprintf(tempstr2,"\t%d\t0",(int)round(dz->parray[k][m+1]));
  3812. else
  3813. sprintf(tempstr2,"\t%d\t1",(int)round(dz->parray[k][m+1]));
  3814. strcat(tempstr,tempstr2);
  3815. }
  3816. fprintf(dz->fp,"%s\n",tempstr);
  3817. }
  3818. }
  3819. // Extend end value to beyond source end
  3820. if(reranged[0])
  3821. sprintf(tempstr,"10000\t%d\t0",(int)round(dz->parray[0][m-1]));
  3822. else
  3823. sprintf(tempstr,"10000\t%d\t1",(int)round(dz->parray[0][m-1]));
  3824. for(k=1;k<dz->iparam[SA_PKCNT];k++) {
  3825. if(reranged[k])
  3826. sprintf(tempstr2,"\t%d\t0",(int)round(dz->parray[k][m-1]));
  3827. else
  3828. sprintf(tempstr2,"\t%d\t1",(int)round(dz->parray[k][m-1]));
  3829. strcat(tempstr,tempstr2);
  3830. }
  3831. fprintf(dz->fp,"%s\n",tempstr);
  3832. return FINISHED;
  3833. }
  3834. /********************************************** RERANGE_OUTOFRANGE_PITCH **************************************
  3835. *
  3836. * If outofrange pitches remian in the filter definition they
  3837. * (1) May cause unwanted glissi at transition points (from one pitch to another) in a filter thread
  3838. * (2) May produce a false reading for the highest possible harmonic in the varibank interface.
  3839. */
  3840. int rerange_outofrange_pitch(int strandindex,int eventindex,dataptr dz)
  3841. {
  3842. int gotpre = 0, gotpost = 0;
  3843. int thisevent, pitchindex;
  3844. double prepitch = 0, postpitch = 0, newpitch;
  3845. if(eventindex > 0) {
  3846. thisevent = eventindex;
  3847. while(thisevent > 0) { // Find 1st earlier pitch which is in range
  3848. thisevent--;
  3849. pitchindex = (thisevent * 2) + 1;
  3850. if(dz->parray[strandindex][pitchindex] < dz->param[SA_BOTRANGE] || dz->parray[strandindex][pitchindex] > dz->param[SA_TOPRANGE])
  3851. continue;
  3852. else {
  3853. gotpre = 1;
  3854. prepitch = dz->parray[strandindex][pitchindex];
  3855. break;
  3856. }
  3857. }
  3858. }
  3859. if(eventindex < dz->envcnt-1) {
  3860. thisevent = eventindex; // Find first later pitch which is in range
  3861. while(thisevent < dz->envcnt) {
  3862. thisevent++;
  3863. pitchindex = (thisevent * 2) + 1;
  3864. if(dz->parray[strandindex][pitchindex] < dz->param[SA_BOTRANGE] || dz->parray[strandindex][pitchindex] > dz->param[SA_TOPRANGE])
  3865. continue;
  3866. else {
  3867. gotpost = 1;
  3868. postpitch = dz->parray[strandindex][pitchindex];
  3869. break;
  3870. }
  3871. }
  3872. }
  3873. if(!gotpre && !gotpost) {
  3874. sprintf(errstr,"ERROR IN OUT-OF-RANGE PITCH PROCESSING.\n");
  3875. return PROGRAM_ERROR;
  3876. }
  3877. if(gotpre && gotpost)
  3878. newpitch = (double)((int)round((prepitch + postpitch)/2.0));
  3879. else if(!gotpre)
  3880. newpitch = postpitch;
  3881. else
  3882. newpitch = prepitch;
  3883. pitchindex = (eventindex * 2) + 1;
  3884. dz->parray[strandindex][pitchindex] = newpitch;
  3885. return FINISHED;
  3886. }