specanal.c 157 KB

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