| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186 |
- /*
- * Copyright (c) 1983-2023 Trevor Wishart and Composers Desktop Project Ltd
- * http://www.trevorwishart.co.uk
- * http://www.composersdesktop.com
- *
- This file is part of the CDP System.
-
- The CDP System is free software; you can redistribute it
- and/or modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- The CDP System is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with the CDP System; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307 USA
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <structures.h>
- #include <tkglobals.h>
- #include <pnames.h>
- #include <filetype.h>
- #include <processno.h>
- #include <modeno.h>
- #include <logic.h>
- #include <globcon.h>
- #include <cdpmain.h>
- #include <math.h>
- #include <mixxcon.h>
- #include <osbind.h>
- #include <science.h>
- #include <ctype.h>
- #include <sfsys.h>
- #include <string.h>
- #include <srates.h>
- #include <formants.h>
- #include <speccon.h>
- #define SAFETY 4
- #define SA_CHANS (0)
- #define SA_WINOVLP (1)
- #define SA_FORMANT_BANDS (2)
- #define SA_PICH_LOLM (2) /* low limit of frq search */
- #define SA_PICH_HILM (3) /* high limit of frq search */
- #define SA_PICH_RNGE (4) /* semitone range for frqs to be in tune with expected frq (semitones) */
- #define SA_PICH_SRATIO (5) /* sig-to-noise ratio: below this, window assumed to be (pitchless) noise */
- #define SA_PICH_MATCH (6) /* how many of (MAXIMI=) 8 loudest peaks must be partials */
- #define SA_PICH_VALID (7) /* how many successive windows need to be pitched to confirm true pitch */
- #define SA_PKCNT (2) /* Number of peaks to use in filter design */
- #define SA_TSTEP (3) /* Time-step between pitch-assessments: mS */
- #define SA_BOTRANGE (4) /* Lowest acceptable pitch (MIDI) */
- #define SA_TOPRANGE (5) /* Highest acceptable pitch (MIDI) */
- #define SA_GATE (6) /* Level, relative to maxlevel, at which signal assumed to be silence */
- #define SA_MIN_SMOOTH_SET (3) /* minimum number of adjacent windows to be pitched, when smoothing */
- #define PEAK_LIMIT (.05)
- #define MAX_GLISRATE (16.0) /* Assumptions: pitch can't move faster than 16 octaves per sec: MAX_GLISRATE */
- /* Possible movement from window-to-window = MAX_GLISRATE * dz->frametime */
- #define LAST_SMOOTH_NOT_SET (-1)
- #define EIGHT_OVER_SEVEN (1.142857143)
- #define MAXIMUM_PARTIAL (64)
- #define ALMOST_TWO (1.75)
- // Pitch-absent markers
- // NOT_SOUND = -2
- // NOT_PITCH = -1
- #define SA_TRANSIT 0.05 // Transition time when stepping from one pitch to another
- #define SA_PVOC_TEST (0)
- #define SA_FFT (1)
- #define SA_PVOC (2)
- #define SA_LOGFFT (3)
- #define SA_CEPSTRUM (4)
- #define SA_FORMANTS (5)
- #define SA_AVERAGE (6)
- #define SA_FILTER (7)
- #define SA_TEMPERED (8)
- #define SA_HFVARY (9)
- #define SA_IGNORE_AMP (0)
- #define SA_NO_HARMONICS (1)
- #define SA_MIDILIST (2)
- #define SA_DECHROM (3)
- #define SA_DDOWNOCT (4)
- #define SA_DDOWN2OCT (5)
- #define SA_DOWNOCT (0)
- #define SA_DOWN2OCT (1)
- #define CHAN_SRCHRANGE_F (4)
- #define BINCNT (128) /* Number of semitone bins */
- #define envcnt rampbrksize
- #define framecnt ringsize
- #define pitchcnt temp_sampsize
- static double quartertone;
- //#ifdef unix
- #define round(x) lround((x))
- //#endif
- #ifndef HUGE
- #define HUGE 3.40282347e+38F
- #endif
- char errstr[2400];
- int anal_infiles = 1;
- int sloom = 0;
- int sloombatch = 0;
- const char* cdp_version = "6.2.0";
- //CDP LIB REPLACEMENTS
- static int check_specanal_param_validity_and_consistency(dataptr dz);
- static int setup_specanal_application(dataptr dz);
- static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
- static int parse_infile_and_check_type(char **cmdline,dataptr dz);
- static int setup_specanal_param_ranges_and_defaults(dataptr dz);
- static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz);
- static int setup_and_init_input_param_activity(dataptr dz,int tipc);
- static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
- static int establish_application(dataptr dz);
- static int initialise_vflags(dataptr dz);
- static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
- static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
- static int mark_parameter_types(dataptr dz,aplptr ap);
- static int assign_file_data_storage(int infilecnt,dataptr dz);
- static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
- static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
- static int get_the_mode_from_cmdline(char *str,dataptr dz);
- static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
- static int specanal(dataptr dz);
- static void hamming(float *win,int winLen,int even);
- static int pvoc_float_array(int nnn,float **ptr);
- static int sndwrite_header(int N2,int *Nchans,float *arate,float R,int D,int origsize,int *isr,int M,dataptr dz);
- static int write_samps_pvoc(float *bbuf,int samps_to_write,dataptr dz);
- 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);
- 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[]);
- static int reals_(float *a, float *b, int n, int isn);
- static int sa_initialise_specenv(dataptr dz);
- static int sa_set_specenv_frqs(dataptr dz);
- static int sa_setup_octaveband_steps(double **interval,dataptr dz);
- static int sa_setup_low_octave_bands(int arraycnt,dataptr dz);
- static int sa_extract_specenv(float *anal,dataptr dz);
- static int is_a_harmonic_x(double frq1,double frq2);
- static int extract_env_from_sndfile(dataptr dz);
- static int get_tempered_pitch(float *averages, float *averages2, float *averages3, dataptr dz);
- static int smooth_and_output_tempered_pitch(dataptr dz);
- static int check_specanal_param_validity_and_consistency2(dataptr dz);
- static int get_tempered_hf(float *averages, float *averages2, float *averages3, dataptr dz);
- static int smooth_and_output_varying_hf(dataptr dz);
- static int rerange_outofrange_pitch(int strandindex,int eventindex,dataptr dz);
- //RWD 2025 trap oversize channel count for .ana format
- static int checkchans4format(int chans, const char* fname);
- /**************************************** MAIN *********************************************/
- int main(int argc,char *argv[])
- {
- int exit_status;
- dataptr dz = NULL;
- char **cmdline;
- int cmdlinecnt;
- // aplptr ap;
- int is_launched = FALSE;
- quartertone = sqrt(SEMITONE_INTERVAL);
- if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
- fprintf(stdout,"%s\n",cdp_version);
- fflush(stdout);
- return 0;
- }
- /* CHECK FOR SOUNDLOOM */
- if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
- sloom = 0;
- sloombatch = 1;
- }
- if(sflinit("cdp")){
- sfperror("cdp: initialisation\n");
- return(FAILED);
- }
- /* SET UP THE PRINCIPLE DATASTRUCTURE */
- if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if(!sloom) {
- if(argc == 1) {
- usage1();
- return(FAILED);
- } else if(argc == 2) {
- usage2(argv[1]);
- return(FAILED);
- }
- }
- if(!sloom) {
- if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- cmdline = argv;
- cmdlinecnt = argc;
- if((get_the_process_no(argv[0],dz))<0)
- return(FAILED);
- cmdline++;
- cmdlinecnt--;
- dz->maxmode = 10;
- if((exit_status = get_the_mode_from_cmdline(cmdline[0],dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(exit_status);
- }
- cmdline++;
- cmdlinecnt--;
- // setup_particular_application =
- if((exit_status = setup_specanal_application(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- } else {
- //parse_TK_data() =
- if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(exit_status);
- }
- }
- // ap = dz->application;
- // parse_infile_and_hone_type() =
- if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // open_first_infile CDP LIB
- if((exit_status = open_first_infile(cmdline[0],dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- cmdlinecnt--;
- cmdline++;
- // setup_param_ranges_and_defaults() =
- if((exit_status = setup_specanal_param_ranges_and_defaults(dz))<0) {
- exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // handle_extra_infiles() : redundant
- // handle_outfile() =
- if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // handle_formants() redundant
- // handle_formant_quiksearch() redundant
- // handle_special_data() redundant
-
- if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- // check_param_validity_and_consistency....
- if((exit_status = check_specanal_param_validity_and_consistency(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- is_launched = TRUE;
- if((exit_status = specanal(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- switch(dz->mode) {
- case(SA_PVOC_TEST):
- dz->process = PVOC_ANAL;
- if((exit_status = complete_output(dz))<0) {
- dz->process = SPECANAL;
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- dz->process = SPECANAL;
- break;
- default:
- if((exit_status = complete_output(dz))<0) {
- print_messages_and_close_sndfiles(exit_status,is_launched,dz);
- return(FAILED);
- }
- break;
- }
- exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz);
- free(dz);
- return(SUCCEEDED);
- }
- /**********************************************
- REPLACED CDP LIB FUNCTIONS
- **********************************************/
- /****************************** SET_PARAM_DATA *********************************/
- int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
- {
- ap->special_data = (char)special_data;
- ap->param_cnt = (char)paramcnt;
- ap->max_param_cnt = (char)maxparamcnt;
- if(ap->max_param_cnt>0) {
- if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->param_list,paramlist);
- }
- return(FINISHED);
- }
- /****************************** SET_VFLGS *********************************/
- int set_vflgs
- (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
- {
- ap->option_cnt = (char) optcnt; /*RWD added cast */
- if(optcnt) {
- if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->option_list,optlist);
- if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->option_flags,optflags);
- }
- ap->vflag_cnt = (char) vflagcnt;
- ap->variant_param_cnt = (char) vparamcnt;
- if(vflagcnt) {
- if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->variant_list,varlist);
- if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
- return(MEMORY_ERROR);
- }
- strcpy(ap->variant_flags,varflags);
- }
- return(FINISHED);
- }
- /***************************** APPLICATION_INIT **************************/
- int application_init(dataptr dz)
- {
- int exit_status;
- int storage_cnt;
- int tipc, brkcnt;
- aplptr ap = dz->application;
- if(ap->vflag_cnt>0)
- initialise_vflags(dz);
- tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
- ap->total_input_param_cnt = (char)tipc;
- if(tipc>0) {
- if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
- return(exit_status);
- if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
- return(exit_status);
- if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
- return(exit_status);
- }
- brkcnt = tipc;
- //THERE ARE NO INPUTFILE brktables USED IN THIS PROCESS
- if(brkcnt>0) {
- if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
- return(exit_status);
- }
- if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
- if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
- return(exit_status);
- if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
- return(exit_status);
- }
- if((exit_status = mark_parameter_types(dz,ap))<0)
- return(exit_status);
-
- // establish_infile_constants() replaced by
- dz->infilecnt = 1;
- //establish_bufptrs_and_extra_buffers():
- return(FINISHED);
- }
- /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
- /* RWD mallo changed to calloc; helps debug verison run as release! */
- int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
- {
- if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
- return(MEMORY_ERROR);
- }
- if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
- return(MEMORY_ERROR);
- }
- if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
- return(MEMORY_ERROR);
- }
- if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
- sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
- int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
- {
- int n;
- for(n=0;n<storage_cnt;n++) {
- dz->is_int[n] = (char)0;
- dz->no_brk[n] = (char)0;
- }
- return(FINISHED);
- }
- /***************************** MARK_PARAMETER_TYPES **************************/
- int mark_parameter_types(dataptr dz,aplptr ap)
- {
- int n, m; /* PARAMS */
- for(n=0;n<ap->max_param_cnt;n++) {
- switch(ap->param_list[n]) {
- case('0'): break; /* dz->is_active[n] = 0 is default */
- case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
- case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
- case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
- case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
- default:
- sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- } /* OPTIONS */
- for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
- switch(ap->option_list[n]) {
- case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
- case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
- default:
- sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- } /* VARIANTS */
- for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
- switch(ap->variant_list[n]) {
- case('0'): break;
- case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
- case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
- default:
- sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- } /* INTERNAL */
- for(n=0,
- m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
- switch(ap->internal_param_list[n]) {
- case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
- case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
- case('d'): dz->no_brk[m] = (char)1; break;
- default:
- sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
- return(PROGRAM_ERROR);
- }
- }
- return(FINISHED);
- }
- /************************ HANDLE_THE_OUTFILE *********************/
- int handle_the_outfile(int *cmdlinecnt,char ***cmdline,dataptr dz)
- {
- char *filename = (*cmdline)[0];
- if(filename[0]=='-' && filename[1]=='f') {
- dz->floatsam_output = 1;
- dz->true_outfile_stype = SAMP_FLOAT;
- filename+= 2;
- }
- if(!sloom) {
- if(file_has_invalid_startchar(filename) || value_is_numeric(filename)) {
- sprintf(errstr,"Outfile name %s has invalid start character(s) or looks too much like a number.\n",filename);
- return(DATA_ERROR);
- }
- }
- strcpy(dz->outfilename,filename);
- (*cmdline)++;
- (*cmdlinecnt)--;
- return(FINISHED);
- }
- /***************************** ESTABLISH_APPLICATION **************************/
- int establish_application(dataptr dz)
- {
- aplptr ap;
- if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
- sprintf(errstr,"establish_application()\n");
- return(MEMORY_ERROR);
- }
- ap = dz->application;
- memset((char *)ap,0,sizeof(struct applic));
- return(FINISHED);
- }
- /************************* INITIALISE_VFLAGS *************************/
- int initialise_vflags(dataptr dz)
- {
- int n;
- if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<dz->application->vflag_cnt;n++)
- dz->vflag[n] = FALSE;
- return FINISHED;
- }
- /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
- int setup_input_param_defaultval_stores(int tipc,aplptr ap)
- {
- int n;
- if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<tipc;n++)
- ap->default_val[n] = 0.0;
- return(FINISHED);
- }
- /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
- int setup_and_init_input_param_activity(dataptr dz,int tipc)
- {
- int n;
- if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
- sprintf(errstr,"setup_and_init_input_param_activity()\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<tipc;n++)
- dz->is_active[n] = (char)0;
- return(FINISHED);
- }
- /************************* SETUP_SPECANAL_APPLICATION *******************/
- int setup_specanal_application(dataptr dz)
- {
- int exit_status;
- aplptr ap;
- if((exit_status = establish_application(dz))<0) // GLOBAL
- return(FAILED);
- ap = dz->application;
- // SEE parstruct FOR EXPLANATION of next 2 functions
- if(dz->mode == SA_FORMANTS) {
- if((exit_status = set_param_data(ap,0 ,3,3,"iii"))<0)
- return(FAILED);
- } else if(dz->mode == SA_FILTER) {
- if((exit_status = set_param_data(ap,0 ,4,3,"iii0"))<0)
- return(FAILED);
- } else if(dz->mode == SA_TEMPERED) {
- if((exit_status = set_param_data(ap,0 ,4,3,"ii0d"))<0)
- return(FAILED);
- } else if(dz->mode == SA_HFVARY) {
- if((exit_status = set_param_data(ap,0 ,4,4,"iiid"))<0)
- return(FAILED);
- } else {
- if((exit_status = set_param_data(ap,0 ,2,2,"ii"))<0)
- return(FAILED);
- }
- // set_legal_infile_structure -->
- dz->has_otherfile = FALSE;
- // assign_process_logic -->
- dz->input_data_type = SNDFILES_ONLY;
- switch(dz->mode) {
- case(SA_FFT):
- case(SA_LOGFFT):
- case(SA_CEPSTRUM):
- case(SA_FORMANTS):
- if((exit_status = set_vflgs(ap,"",0,"","n",1,0,"0"))<0)
- return(FAILED);
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- case(SA_PVOC):
- if((exit_status = set_vflgs(ap,"",0,"","nf",2,0,"00"))<0)
- return(FAILED);
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- case(SA_AVERAGE):
- if((exit_status = set_vflgs(ap,"",0,"","0",0,0,""))<0)
- return(FAILED);
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- case(SA_FILTER):
- if((exit_status = set_vflgs(ap,"",0,"","ahmcdD",6,0,"000000"))<0)
- return(FAILED);
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- case(SA_TEMPERED):
- if((exit_status = set_vflgs(ap,"btg",3,"iid","",0,0,""))<0)
- return(FAILED);
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- case(SA_HFVARY):
- if((exit_status = set_vflgs(ap,"btg",3,"iid","d",2,0,"00"))<0)
- return(FAILED);
- dz->process_type = TO_TEXTFILE;
- dz->outfiletype = TEXTFILE_OUT;
- break;
- default:
- if((exit_status = set_vflgs(ap,"",0,"","",0,0,""))<0)
- return(FAILED);
- dz->process_type = BIG_ANALFILE;
- dz->outfiletype = ANALFILE_OUT;
- }
- return application_init(dz); //GLOBAL
- }
- /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
- int parse_infile_and_check_type(char **cmdline,dataptr dz)
- {
- int exit_status;
- infileptr infile_info;
- if(!sloom) {
- if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
- return(MEMORY_ERROR);
- } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
- sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
- return(DATA_ERROR);
- } else if(infile_info->filetype != SNDFILE) {
- sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
- return(DATA_ERROR);
- } else if(infile_info->channels != 1) {
- sprintf(errstr,"File %s is not of correct type (must be mono)\n",cmdline[0]);
- return(DATA_ERROR);
- } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
- sprintf(errstr,"Failed to copy file parsing information\n");
- return(PROGRAM_ERROR);
- }
- free(infile_info);
- }
- return(FINISHED);
- }
- /************************* SETUP_SPECANAL_PARAM_RANGES_AND_DEFAULTS *******************/
- int setup_specanal_param_ranges_and_defaults(dataptr dz)
- {
- int exit_status;
- aplptr ap = dz->application;
- // set_param_ranges()
- ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
- // NB total_input_param_cnt is > 0 !!!
- if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
- return(FAILED);
- // get_param_ranges()
- ap->lo[SA_CHANS] = (double)2;
- ap->hi[SA_CHANS] = (double)PA_MAX_PVOC_CHANS;
- ap->default_val[SA_CHANS] = PA_DEFAULT_PVOC_CHANS;
- ap->lo[SA_WINOVLP] = (double)1;
- ap->hi[SA_WINOVLP] = (double)4;
- ap->default_val[SA_WINOVLP] = 0.0;
- if(dz->mode == SA_FORMANTS) {
- ap->lo[SA_FORMANT_BANDS] = (double)1;
- ap->hi[SA_FORMANT_BANDS] = (double)12;
- ap->default_val[SA_FORMANT_BANDS] = 4.0;
- } else {
- if (dz->mode == SA_FILTER || dz->mode == SA_HFVARY) {
- ap->lo[SA_PKCNT] = 1;
- ap->hi[SA_PKCNT] = 128;
- ap->default_val[SA_PKCNT] = 6;
- }
- if (dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
- ap->lo[SA_TSTEP] = 5;
- ap->hi[SA_TSTEP] = (dz->duration/2.0) * SECS_TO_MS;
- ap->default_val[SA_TSTEP] = 100;
- ap->lo[SA_BOTRANGE] = 0;
- ap->hi[SA_BOTRANGE] = 127;
- ap->default_val[SA_BOTRANGE] = 0;
- ap->lo[SA_TOPRANGE] = 0;
- ap->hi[SA_TOPRANGE] = 127;
- ap->default_val[SA_TOPRANGE] = 127;
- ap->lo[SA_GATE] = 0;
- ap->hi[SA_GATE] = 0.5;
- ap->default_val[SA_GATE] = 0.1;
- }
- }
- dz->maxmode = 10;
- if(!sloom)
- put_default_vals_in_all_params(dz);
- return(FINISHED);
- }
- /********************************* PARSE_SLOOM_DATA *********************************/
- int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
- {
- int exit_status;
- int cnt = 1, infilecnt;
- int filesize, insams, inbrksize;
- double dummy;
- int true_cnt = 0;
- // aplptr ap;
- while(cnt<=PRE_CMDLINE_DATACNT) {
- if(cnt > argc) {
- sprintf(errstr,"Insufficient data sent from TK\n");
- return(DATA_ERROR);
- }
- switch(cnt) {
- case(1):
- if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
- sprintf(errstr,"Cannot read process no. sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(2):
- if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
- sprintf(errstr,"Cannot read mode no. sent from TK\n");
- return(DATA_ERROR);
- }
- if(dz->mode > 0)
- dz->mode--;
- //setup_particular_application() =
- if((exit_status = setup_specanal_application(dz))<0)
- return(exit_status);
- // ap = dz->application;
- break;
- case(3):
- if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
- sprintf(errstr,"Cannot read infilecnt sent from TK\n");
- return(DATA_ERROR);
- }
- if(infilecnt < 1) {
- true_cnt = cnt + 1;
- cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
- }
- if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
- return(exit_status);
- break;
- case(INPUT_FILETYPE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
- sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
- return(DATA_ERROR);
- }
- break;
- case(INPUT_FILESIZE+4):
- if(sscanf(argv[cnt],"%d",&filesize)!=1) {
- sprintf(errstr,"Cannot read infilesize sent from TK\n");
- return(DATA_ERROR);
- }
- dz->insams[0] = filesize;
- break;
- case(INPUT_INSAMS+4):
- if(sscanf(argv[cnt],"%d",&insams)!=1) {
- sprintf(errstr,"Cannot read insams sent from TK\n");
- return(DATA_ERROR);
- }
- dz->insams[0] = insams;
- break;
- case(INPUT_SRATE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
- sprintf(errstr,"Cannot read srate sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_CHANNELS+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
- sprintf(errstr,"Cannot read channels sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_STYPE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
- sprintf(errstr,"Cannot read stype sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ORIGSTYPE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
- sprintf(errstr,"Cannot read origstype sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ORIGRATE+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
- sprintf(errstr,"Cannot read origrate sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MLEN+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
- sprintf(errstr,"Cannot read Mlen sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DFAC+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
- sprintf(errstr,"Cannot read Dfac sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ORIGCHANS+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
- sprintf(errstr,"Cannot read origchans sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_SPECENVCNT+4):
- if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
- sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
- return(DATA_ERROR);
- }
- dz->specenvcnt = dz->infile->specenvcnt;
- break;
- case(INPUT_WANTED+4):
- if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
- sprintf(errstr,"Cannot read wanted sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_WLENGTH+4):
- if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
- sprintf(errstr,"Cannot read wlength sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_OUT_CHANS+4):
- if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
- sprintf(errstr,"Cannot read out_chans sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- /* RWD these chanegs to samps - tk will have to deal with that! */
- case(INPUT_DESCRIPTOR_BYTES+4):
- if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
- sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_IS_TRANSPOS+4):
- if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
- sprintf(errstr,"Cannot read is_transpos sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_COULD_BE_TRANSPOS+4):
- if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
- sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_COULD_BE_PITCH+4):
- if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
- sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DIFFERENT_SRATES+4):
- if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
- sprintf(errstr,"Cannot read different_srates sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DUPLICATE_SNDS+4):
- if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
- sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_BRKSIZE+4):
- if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
- sprintf(errstr,"Cannot read brksize sent from TK\n");
- return(DATA_ERROR);
- }
- if(inbrksize > 0) {
- switch(dz->input_data_type) {
- case(WORDLIST_ONLY):
- break;
- case(PITCH_AND_PITCH):
- case(PITCH_AND_TRANSPOS):
- case(TRANSPOS_AND_TRANSPOS):
- dz->tempsize = inbrksize;
- break;
- case(BRKFILES_ONLY):
- case(UNRANGED_BRKFILE_ONLY):
- case(DB_BRKFILES_ONLY):
- case(ALL_FILES):
- case(ANY_NUMBER_OF_ANY_FILES):
- if(dz->extrabrkno < 0) {
- sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
- return(DATA_ERROR);
- }
- if(dz->brksize == NULL) {
- sprintf(errstr,"CDP has not established storage space for input brktable.\n");
- return(PROGRAM_ERROR);
- }
- dz->brksize[dz->extrabrkno] = inbrksize;
- break;
- default:
- sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
- dz->input_data_type);
- return(PROGRAM_ERROR);
- }
- break;
- }
- break;
- case(INPUT_NUMSIZE+4):
- if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
- sprintf(errstr,"Cannot read numsize sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_LINECNT+4):
- if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
- sprintf(errstr,"Cannot read linecnt sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ALL_WORDS+4):
- if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
- sprintf(errstr,"Cannot read all_words sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_ARATE+4):
- if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
- sprintf(errstr,"Cannot read arate sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_FRAMETIME+4):
- if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
- sprintf(errstr,"Cannot read frametime sent from TK\n");
- return(DATA_ERROR);
- }
- dz->frametime = (float)dummy;
- break;
- case(INPUT_WINDOW_SIZE+4):
- if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
- sprintf(errstr,"Cannot read window_size sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_NYQUIST+4):
- if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
- sprintf(errstr,"Cannot read nyquist sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_DURATION+4):
- if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
- sprintf(errstr,"Cannot read duration sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MINBRK+4):
- if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
- sprintf(errstr,"Cannot read minbrk sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MAXBRK+4):
- if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
- sprintf(errstr,"Cannot read maxbrk sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MINNUM+4):
- if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
- sprintf(errstr,"Cannot read minnum sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- case(INPUT_MAXNUM+4):
- if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
- sprintf(errstr,"Cannot read maxnum sent from TK\n");
- return(DATA_ERROR);
- }
- break;
- default:
- sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
- return(PROGRAM_ERROR);
- }
- cnt++;
- }
- if(cnt!=PRE_CMDLINE_DATACNT+1) {
- sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
- return(DATA_ERROR);
- }
- if(true_cnt)
- cnt = true_cnt;
- *cmdlinecnt = 0;
- while(cnt < argc) {
- if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
- return(exit_status);
- cnt++;
- }
- return(FINISHED);
- }
- /********************************* GET_TK_CMDLINE_WORD *********************************/
- int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
- {
- if(*cmdlinecnt==0) {
- if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
- return(MEMORY_ERROR);
- }
- } else {
- if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
- return(MEMORY_ERROR);
- }
- }
- if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
- return(MEMORY_ERROR);
- }
- strcpy((*cmdline)[*cmdlinecnt],q);
- (*cmdlinecnt)++;
- return(FINISHED);
- }
- /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
- int assign_file_data_storage(int infilecnt,dataptr dz)
- {
- int exit_status;
- int no_sndfile_system_files = FALSE;
- dz->infilecnt = infilecnt;
- if((exit_status = allocate_filespace(dz))<0)
- return(exit_status);
- if(no_sndfile_system_files)
- dz->infilecnt = 0;
- return(FINISHED);
- }
- /************************* redundant functions: to ensure libs compile OK *******************/
- int assign_process_logic(dataptr dz)
- {
- return(FINISHED);
- }
- void set_legal_infile_structure(dataptr dz)
- {}
- int set_legal_internalparam_structure(int process,int mode,aplptr ap)
- {
- return(FINISHED);
- }
- int setup_internal_arrays_and_array_pointers(dataptr dz)
- {
- return(FINISHED);
- }
- int establish_bufptrs_and_extra_buffers(dataptr dz)
- {
- return(FINISHED);
- }
- int read_special_data(char *str,dataptr dz)
- {
- return(FINISHED);
- }
- int inner_loop
- (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
- {
- return(FINISHED);
- }
- int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
- {
- return(FINISHED);
- }
- /******************************** USAGE1 ********************************/
- int usage1(void)
- {
- usage2("specanal");
- return(USAGE_ONLY);
- }
- /**************************** CHECK_SPECANAL_PARAM_VALIDITY_AND_CONSISTENCY *****************************/
- int check_specanal_param_validity_and_consistency(dataptr dz)
- {
- int exit_status;
- dz->is_mapping = 0;
- (dz->iparam[SA_WINOVLP])--;
- 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)
- //RWD 2025
- if(checkchans4format(dz->iparam[SA_CHANS],dz->outfilename) == 0) {
- sprintf(errstr,"Requested analysis channel count %d > 8192: too large for .ana format\n",dz->iparam[SA_CHANS]);
- return DATA_ERROR;
- }
- dz->wanted = dz->iparam[SA_CHANS] + 2;
- if(dz->mode == SA_FORMANTS) {
- if((exit_status = sa_initialise_specenv(dz)) < 0)
- return(exit_status);
- if((exit_status = sa_set_specenv_frqs(dz)) < 0)
- return(exit_status);
- } else if (dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
- if(dz->iparam[SA_BOTRANGE] >= dz->iparam[SA_TOPRANGE] - 12) {
- sprintf(errstr,"INVALID PITCH RANGE: MUST BE > 1 Octave\n");
- return DATA_ERROR;
- }
- if(dz->vflag[SA_DOWNOCT] && dz->vflag[SA_DOWN2OCT]) {
- sprintf(errstr,"CANNOT TRANSPOSE DOWN BY 8va ~AND~ BY TWO 8vas\n");
- return DATA_ERROR;
- }
- } else if (dz->mode == SA_FILTER) {
- if(dz->vflag[SA_DDOWNOCT] && dz->vflag[SA_DDOWN2OCT]) {
- sprintf(errstr,"CANNOT TRANSPOSE DOWN BY 8va ~AND~ BY TWO 8vas\n");
- return DATA_ERROR;
- }
- }
- return FINISHED;
- }
- /**************************** CHECK_SPECANAL_PARAM_VALIDITY_AND_CONSISTENCY_2 *****************************/
- int check_specanal_param_validity_and_consistency2(dataptr dz)
- {
- int exit_status, n;
- dz->param[SA_TSTEP] = dz->param[SA_TSTEP] * MS_TO_SECS;
- dz->framecnt = (int)round(dz->param[SA_TSTEP]/dz->frametime);
- dz->param[SA_TSTEP] = dz->framecnt * dz->frametime;
- dz->iparam[SA_TSTEP] = (int)round(dz->param[SA_TSTEP] * dz->infile->srate);
- dz->envcnt = dz->insams[0]/dz->iparam[SA_TSTEP];
- if(dz->envcnt * dz->iparam[SA_TSTEP] < dz->insams[0])
- dz->envcnt++;
- if((dz->env = (float *)calloc(dz->envcnt + SAFETY,sizeof(float))) == 0) {
- sprintf(errstr, "Can't allocate buffer for reading envelope.\n");
- return(MEMORY_ERROR);
- }
- memset((char *)dz->env,0,(dz->envcnt + SAFETY) * sizeof(float));
- // Buffer for reading sndfile to get envelope
- if((dz->sampbuf = (float **)malloc(sizeof(float *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers for extracting envelope.(1)\n");
- return(MEMORY_ERROR);
- }
- if((dz->sampbuf[0] = (float *)malloc((dz->iparam[SA_TSTEP] * 2) * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing sample buffers for extracting envelope.(2)\n");
- return(MEMORY_ERROR);
- }
- if((exit_status = extract_env_from_sndfile(dz)) < 0)
- return(exit_status);
- if((dz->iparray = (int **)malloc(8 * sizeof(int *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing peaks data storage 0\n");
- return(MEMORY_ERROR);
- }
- if((dz->iparray[0] = (int *)malloc((dz->envcnt+SAFETY) * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing peaks data storage 1\n");
- return(MEMORY_ERROR);
- }
- if(dz->mode == SA_HFVARY) {
- for(n=1; n < 8;n++) {
- if((dz->iparray[n] = (int *)malloc((dz->envcnt+SAFETY) * sizeof(int)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing peaks data storage %d\n",n+1);
- return(MEMORY_ERROR);
- }
- }
- }
- if((dz->parray = (double **)malloc(8 * sizeof(double *)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing pitch data storage 0\n");
- return(MEMORY_ERROR);
- }
- if((dz->parray[0] = (double *)malloc((dz->envcnt+SAFETY) * 2 * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing pitch data storage 1\n");
- return(MEMORY_ERROR);
- }
- if(dz->mode == SA_HFVARY) {
- for(n=1; n < dz->iparam[SA_PKCNT];n++) {
- if((dz->parray[n] = (double *)malloc((dz->envcnt+SAFETY) * 2 * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing pitch data storage %d\n",n+1);
- return(MEMORY_ERROR);
- }
- }
- }
- dz->pitchcnt = 0;
- return FINISHED;
- }
- /******************************** DBTOLEVEL ***********************/
- double dbtolevel(double val)
- {
- int isneg = 0;
- if(flteq(val,0.0))
- return(1.0);
- if(val < 0.0) {
- val = -val;
- isneg = 1;
- }
- val /= 20.0;
- val = pow(10.0,val);
- if(isneg)
- val = 1.0/val;
- return(val);
- }
- /********************************************************************************************/
- int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
- {
- if(!strcmp(prog_identifier_from_cmdline,"specanal")) dz->process = SPECANAL;
- else {
- sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
- return(USAGE_ONLY);
- }
- return(FINISHED);
- }
- /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
- int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
- {
- int n;
- if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
- return(MEMORY_ERROR);
- }
- if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
- return(MEMORY_ERROR);
- }
- if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
- return(MEMORY_ERROR);
- }
- if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
- return(MEMORY_ERROR);
- }
- if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
- return(MEMORY_ERROR);
- }
- if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
- return(MEMORY_ERROR);
- }
- if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
- sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
- return(MEMORY_ERROR);
- }
- for(n=0;n<brkcnt;n++) {
- dz->brk[n] = NULL;
- dz->brkptr[n] = NULL;
- dz->brkinit[n] = 0;
- dz->brksize[n] = 0;
- }
- return(FINISHED);
- }
- /******************************** USAGE2 ********************************/
- int usage2(char *str)
- {
- if(!strcmp(str,"specanal")) {
- fprintf(stderr,
- "Generate various types of analysis data, or filter data from sound.\n"
- "\n"
- "USAGE:\n"
- "specanal specanal 1 inf analofil chs ovlp\n"
- "specanal specanal 2,4,5 inf txtofils chs ovlp [-n]\n"
- "specanal specanal 3 inf txtofils chs ovlp [-n] [-f]\n"
- "specanal specanal 6 inf txtofils chs ovlp fbands [-n]\n"
- "specanal specanal 7 inf txtofil chs ovlp\n"
- "specanal specanal 8 inf txtofil chs ovlp pkcnt [-a] [-h] [-c] [-m] [-d|-D]\n"
- "specanal specanal 9 inf txtofil chs ovlp tstep [-bbot] [-ttop] [-ggate]\n"
- "specanal specanal 10 inf txtofil chs ovlp pkcnt tstep [-bbot] [-ttop] [-ggate] [-d|-D]\n"
- "\n"
- "INF A Mono soundfile.\n"
- "TXTOFIL(S) (Generic) name for text output file(s).\n"
- "ANALOFIL Analysis output file.\n"
- "CHS Number of analysis points : a multiple of 4 (4 - 32768).\n" //RWD 2025 was 16380
- "OVLP analysis window overlap (1-4), for PVOC analysis.\n"
- "FBANDS Number of formant peaks to find.\n"
- "-n Normalise output display.\n"
- "-f Force frequencies into ascending order.\n"
- "\n"
- "Mode 1: PVOC anal output as analfile.\n"
- "\n"
- "Modes 2-6 generate sets of text outfiles, 1 for each analysis window from input\n"
- " (except first - zeroed - window).\n"
- " These can be used to run a \"movie\" of the data in Soundloom.\n"
- "\n"
- "Mode 2: FFT data as magnitude and channel centre frequency.\n"
- "Mode 3: PVOC data as amplitude and frequency.\n"
- "Mode 4: LOG of FFT magnitudes (output always noremalised).\n"
- "Mode 5: Cepstrum (FFT of log FFT) (output always normalised).\n"
- "Mode 6: Generate Formant Envelope.\n"
- "\n"
- "Modes 7-10 generate 1 textfile, a MIDI list, or a MIDI varibank filterdata file.\n"
- "\n"
- "Mode 7: Signal level, at each semitone bin, averaged over entire sound.\n"
- "Mode 8: Derived Harmonic Field (HF) of entire sound\n"
- " converted to varibank-filter data, or a list of MIDI values.\n"
- "Mode 9: (Changing) Pitch, in tempered scale: output as MIDI-type varibank file.\n"
- " NB Pitch of most prominent partial, not necessarily of fundamental.\n"
- "Mode 10: (Changing) HF in tempered scale: output as MIDI-type varibank file.\n"
- "\n"
- "PKCNT Number of peaks to use as filter frequencies.\n"
- " (Run Mode 7 first to view the spectral envelope as a brkfile).\n"
- "TSTEP Time step, in mS, between pitch-assessments.\n"
- "BOT Minimum acceptable pitch (MIDI).\n"
- "TOP Maximum acceptable pitch (MIDI).\n"
- "GATE Level (relative to max) at which signal ignored (no pitch assigned).\n"
- "-a Ignore relative amp of peaks (dflt, use relative amps) in filter definition.\n"
- "-h Eliminate any peaks which are harmonics of others.\n"
- "-c Dechromaticise: remove quieter pitch of any pair at semitone interval.\n"
- "-m Outputs list of MIDI values (default: MIDI-type varibank filter file).\n"
- "-d Transpose entire filter down by an octave.\n"
- "-D Transpose entire filter down by two octaves.\n"
- "\n");
- } else {
- fprintf(stdout,"Unknown option '%s'\n",str);
- fflush(stdout);
- }
- return(USAGE_ONLY);
- }
- int usage3(char *str1,char *str2)
- {
- fprintf(stderr,"Insufficient parameters on command line.\n");
- return(USAGE_ONLY);
- }
- /****************************** GET_MODE *********************************/
- int get_the_mode_from_cmdline(char *str,dataptr dz)
- {
- char temp[200], *p;
- if(sscanf(str,"%s",temp)!=1) {
- sprintf(errstr,"Cannot read mode of program.\n");
- return(USAGE_ONLY);
- }
- p = temp + strlen(temp) - 1;
- while(p >= temp) {
- if(!isdigit(*p)) {
- fprintf(stderr,"Invalid mode of program entered.\n");
- return(USAGE_ONLY);
- }
- p--;
- }
- if(sscanf(str,"%d",&dz->mode)!=1) {
- fprintf(stderr,"Cannot read mode of program.\n");
- return(USAGE_ONLY);
- }
- if(dz->mode <= 0 || dz->mode > dz->maxmode) {
- fprintf(stderr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
- return(USAGE_ONLY);
- }
- dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
- return(FINISHED);
- }
- /****************************** HAMMING ******************************/
- void hamming(float *win,int winLen,int even)
- {
- float Pi,ftmp;
- int i;
- /***********************************************************
- Pi = (float)((double)4.*atan((double)1.));
- ***********************************************************/
- Pi = (float)PI;
- ftmp = Pi/winLen;
- if (even) {
- for (i=0; i<winLen; i++)
- *(win+i) = (float)((double).54 + (double).46*cos((double)(ftmp*((float)i+.5))));
- *(win+winLen) = 0.0f;}
- else{ *(win) = 1.0f;
- for (i=1; i<=winLen; i++)
- *(win+i) =(float)((double).54 + (double).46*cos((double)(ftmp*(float)i)));
- }
- return;
- }
- /****************************** FLOAT_ARRAY ******************************/
- int pvoc_float_array(int nnn,float **ptr)
- { /* set up a floating point array length nnn. */
- *ptr = (float *) calloc(nnn,sizeof(float));
- if(*ptr==NULL){
- sprintf(errstr,"specanal: insufficient memory\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /****************************** INTEGER_ARRAY ******************************/
- int pvoc_integer_array(int nnn,int **ptr)
- { /* set up a floating point array length nnn. */
- *ptr = (int *) calloc(nnn,sizeof(int));
- if(*ptr==NULL){
- sprintf(errstr,"specanal: insufficient memory\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /****************************** SPECANAL ******************************/
- int specanal(dataptr dz)
- {
- int exit_status, filtercnt, bincnt, n, q, qq, harmonic_amongst_loudest_peaks, peakmidi, chromcnt, downtranspos;
- double rratio, level, centrefrq, frq, range,
- maxsample = 0.0, minsample = 0.0, offset = 0.0, normaliser = 1.0; /* normalisation variables */
- char tempstr[24000], tempstr2[128];
- float *input, /* pointer to start of input buffer */
- *anal, /* pointer to start of analysis buffer */
- *banal, /* pointer to anal[1] (for FFT calls) */
- *averages=NULL, /* pointer to array storing average level of signal in semitone-bins */
- *averages2=NULL,/* pointer to array storing average level of signal in semitone-bins */
- *averages3=NULL,/* pointer to array storing average level of signal in semitone-bins */
- *nextIn, /* pointer to next empty word in input */
- *analWindow, /* pointer to center of analysis window */
- *i0, /* pointer to amplitude channels */
- *i1, /* pointer to frequency channels */
- *oi, /* pointer to old phase channels */
- *oldInPhase, /* pointer to start of input phase buffer */
- *sbuf = NULL, /* input buffer array and pointer */
- *sp;
- int M = 0, /* length of analWindow impulse response */
- D = 0, /* decimatin factor */
- /* RWD */
- /*F = 0,*/ /* fundamental frequency (determines dz->iparam[SA_CHANS]) */
- analWinLen, /* half-length of analysis window */
- i,j,k,kk,jj, /* index variables */
- Dd, /* number of new inputs to read (Dd <= D) */
- N2, /* dz->iparam[SA_CHANS]/2 */
- Mf = 0, /* flag for even M */
- flag = 0, /* end-of-input flag */
- got, /* variables for keeping track of input */
- tocp,
- outframecnt, /* and counting output */
- curtailed = 0,
-
- normalised = 0, /* flags to keep track of file and normalisation types */
- ordered = 0, /* if set, listed frequencies arranged in ascending order */
- is_text_out = 0,
- is_single_text_out = 0, /* pitch analysis procedures */
- is_anal_out = 0,
- *peaks=NULL,
- doskip,
- zeros = 0;
- int sampsize, /* sample size for output file */
- ibuflen, /* length of input buffer */
- nI = 0, /* current input (analysis) sample */
- origsize = 0, /* sample type of file analysed */
- isr, /* sampling rate */
- Nchans, /* no of chans */
- endsamp = PA_VERY_BIG_INT;
- float real, /* real part of analysis data */
- imag, /* imaginary part of analysis data */
- mag, /* magnitude of analysis data */
- phase, /* phase of analysis data */
- angleDif, /* angle difference */
- RoverTwoPi, /* R/D divided by 2*Pi */
- sum, /* scale factor for renormalizing windows */
- rIn, /* decimated sampling rate */
- R, /* input sampling rate */
- kfrq,jfrq,temp, /* for data-ordering calculations */
- peakfrq,
- arate, /* sample rate for header on stdout if analysis output */
- F = 0.0f; /*RWD */
- char *p, thisext[200], thisbasnam[200], filename[200], thisnum[64]; /* handling output multiple outputfile names */
- int orig_chans;
- int orig_srate;
- // fft ARRAYS
-
- float *at, *ck, *bt, *sk;
- int *np;
- int bigenough = 1024, maxpos;
- double maxval;
- if((at = (float *) calloc(bigenough,sizeof(float))) == NULL) {
- sprintf(errstr,"Problem Allocating Array 'at' for FFT\n");
- return(MEMORY_ERROR);
- }
- if((ck = (float *) calloc(bigenough,sizeof(float))) == NULL) {
- sprintf(errstr,"Problem Allocating Array 'ck' for FFT\n");
- return(MEMORY_ERROR);
- }
- if((bt = (float *) calloc(bigenough,sizeof(float))) == NULL) {
- sprintf(errstr,"Problem Allocating Array 'bt' for FFT\n");
- return(MEMORY_ERROR);
- }
- if((sk = (float *) calloc(bigenough,sizeof(float))) == NULL) {
- sprintf(errstr,"Problem Allocating Array 'sk' for FFT\n");
- return(MEMORY_ERROR);
- }
- if((np = (int *) calloc(bigenough,sizeof(int))) == NULL) {
- sprintf(errstr,"Problem Allocating Array 'np' for FFT\n");
- return(MEMORY_ERROR);
- }
- switch(dz->mode) {
- case(SA_FFT):
- case(SA_FORMANTS):
- is_text_out = 1;
- if(dz->vflag[0])
- normalised = 1;
- break;
- case(SA_PVOC):
- is_text_out = 1;
- if(dz->vflag[0])
- normalised = 1;
- if(dz->vflag[1])
- ordered = 1;
- break;
- case(SA_LOGFFT):
- case(SA_CEPSTRUM):
- is_text_out = 1;
- normalised = 1; // Always normalised
- break;
- case(SA_AVERAGE):
- case(SA_TEMPERED):
- case(SA_HFVARY):
- case(SA_FILTER):
- is_single_text_out = 1;
- break;
- default:
- is_anal_out = 1;
- break;
- }
- if(is_text_out || is_single_text_out) {
- p = dz->outfilename; // Get elements of output file names
- while(*p != ENDOFSTR) {
- if(*p == '.') {
- strcpy(thisext,p);
- *p = ENDOFSTR;
- strcpy(thisbasnam,dz->outfilename);
- break;
- }
- p++;
- }
- if(*p == ENDOFSTR) { // If no file extension found, force ".txt"
- strcpy(thisext,".txt");
- strcpy(thisbasnam,dz->outfilename);
- }
- }
- if(sndgetprop(dz->ifd[0],"sample type", (char *) &sampsize, sizeof(int)) < 0){
- sprintf(errstr,"specanal: failure to get sample type\n");
- return(MEMORY_ERROR);
- }
- isr = dz->infile->srate;
- dz->nyquist = isr/2.0;
- R = (float)isr;
- Nchans = dz->infile->channels;
- /*RWD OCT 05 need this to preserved hires infile formats */
- origsize = dz->infile->stype;
- if(flteq(R,0.0)) {
- sprintf(errstr,"Problem: zero sampling rate\n");
- return(DATA_ERROR);
- }
-
- sampsize = SAMP_FLOAT;
- N2 = dz->iparam[SA_CHANS] / 2;
- dz->chwidth = dz->nyquist/(double)N2;
- dz->halfchwidth = dz->chwidth/2;
- F = /*(int)*/(float)(R /(float)dz->iparam[SA_CHANS]); /*RWD*/
- switch(dz->iparam[SA_WINOVLP]){
- case 0: M = 4*dz->iparam[SA_CHANS]; break;
- case 1: M = 2*dz->iparam[SA_CHANS]; break;
- case 2: M = dz->iparam[SA_CHANS]; break;
- case 3: M = N2; break;
- default:
- sprintf(errstr,"specanal: Invalid window overlap factor.\n");
- return(PROGRAM_ERROR);
- }
- Mf = 1 - M%2;
- if (M < 7) {
- fprintf(stdout,"WARNING: analWindow impulse response is too small\n");
- fflush(stdout);
- }
- ibuflen = 4 * M;
- if((D = (int)(M/PA_PVOC_CONSTANT_A)) == 0){
- fprintf(stdout,"WARNING: Decimation too low: adjusted.\n");
- fflush(stdout);
- D = 1;
- }
- arate = (float)(R/D); /* Needed to write to outheader */
- dz->wanted = dz->iparam[SA_CHANS] + 2;
- dz->frametime = (float)(1.0/arate);
- dz->tempsize = dz->insams[0];
- if(dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
- if((exit_status = check_specanal_param_validity_and_consistency2(dz))<0)
- return exit_status;
- if(dz->param[SA_TSTEP] <= dz->frametime * 2) {
- sprintf(errstr,"TIMESTEP TOO SHORT (Minimum > %lf mS)\n",(dz->frametime * 2 * SECS_TO_MS));
- return DATA_ERROR;
- }
- }
- if(is_anal_out) { // Only if Analfile output, write header
- if((exit_status = sndwrite_header(N2,&Nchans,&arate,R,D,origsize,&isr,M,dz))<0)
- return(exit_status);
- dz->process = PVOC_ANAL;
- orig_chans = dz->infile->channels;
- orig_srate = dz->infile->srate;
- dz->infile->channels = dz->outfile->channels;
- dz->infile->srate = dz->outfile->srate;
- if((exit_status = create_sized_outfile(dz->outfilename,dz))<0)
- return(exit_status);
- dz->process = SPECANAL;
- dz->infile->channels = orig_chans;
- dz->infile->srate = orig_srate;
- }
- if((exit_status = pvoc_float_array(M+Mf,&analWindow))<0)
- return(exit_status);
- analWindow += (analWinLen = M/2);
- hamming(analWindow,analWinLen,Mf);
- for (i = 1; i <= analWinLen; i++)
- *(analWindow - i) = *(analWindow + i - Mf);
- if (M > dz->iparam[SA_CHANS]) {
- if (Mf)
- *analWindow *=(float)((double)dz->iparam[SA_CHANS]*sin((double)PI*.5/dz->iparam[SA_CHANS])/(double)(PI*.5));
- for (i = 1; i <= analWinLen; i++)
- *(analWindow + i) *=(float)((double)dz->iparam[SA_CHANS] * sin((double) (PI*(i+.5*Mf)/dz->iparam[SA_CHANS])) / (PI*(i+.5*Mf))); /* D.Timis */
- for (i = 1; i <= analWinLen; i++)
- *(analWindow - i) = *(analWindow + i - Mf);
- }
- sum = 0.0f;
- for (i = -analWinLen; i <= analWinLen; i++)
- sum += *(analWindow + i);
- sum = (float)(2.0/sum); /*factor of 2 comes in later in trig identity*/
- for (i = -analWinLen; i <= analWinLen; i++)
- *(analWindow + i) *= sum;
- /* set up input buffer: nextIn always points to the next empty
- word in the input buffer (i.e., the sample following
- sample number (n + analWinLen)). If the buffer is full,
- then nextIn jumps back to the beginning, and the old
- values are written over. */
- if((exit_status = pvoc_float_array(ibuflen,&input))<0)
- return(exit_status);
- nextIn = input;
- /* set up analysis buffer for (N/2 + 1) channels: The input is real,
- so the other channels are redundant. oldInPhase is used
- in the conversion to remember the previous phase when
- calculating phase difference between successive samples. */
- dz->buflen = dz->iparam[SA_CHANS]+2;
- if((exit_status = pvoc_float_array(dz->buflen,&anal))<0)
- return(exit_status);
- banal = anal + 1;
- if((exit_status = pvoc_float_array(N2+1,&oldInPhase))<0)
- return(exit_status);
- if(dz->mode == SA_AVERAGE || dz->mode == SA_FILTER || dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
- if((exit_status = pvoc_float_array((BINCNT+1) * 2,&averages))<0)
- return(exit_status);
- if((exit_status = pvoc_integer_array(BINCNT,&peaks))<0)
- return(exit_status);
- for(n=0;n<BINCNT;n++)
- peaks[n] = -1;
- averages[0] = (float)(miditohz(0)/SEMITONE_INTERVAL);
- for(jj = 1, kk= 2; jj < BINCNT; jj++, kk+=2)
- averages[kk] = (float)miditohz(jj-0.5);
- }
- if(dz->mode == SA_TEMPERED || dz->mode == SA_HFVARY) {
- if((exit_status = pvoc_float_array((BINCNT+1) * 2,&averages2))<0)
- return(exit_status);
- for(jj = 1, kk= 2; jj < BINCNT; jj++, kk+=2)
- averages2[kk] = (float)miditohz(jj-0.5);
- if((exit_status = pvoc_float_array((BINCNT+1) * 2,&averages3))<0)
- return(exit_status);
- for(jj = 1, kk= 2; jj < BINCNT; jj++, kk+=2)
- averages3[kk] = (float)miditohz(jj-0.5);
- }
- /* initialization: input time starts negative so that the rightmost
- edge of the analysis filter just catches the first non-zero
- input samples; output time is always T times input time. */
- rIn = (float)(R/(float)D);
- RoverTwoPi = (float)(rIn/TWOPI);
- nI = -(analWinLen / D) * D; /* input time (in samples) */
- Dd = analWinLen + nI + 1; /* number of new inputs to read */
- flag = 1;
- /* main loop: If endsamp is not specified it is assumed to be very large
- and then readjusted when fgetfloat detects the end of input. */
- display_virtual_time(0L,dz);
- if((sbuf = (float *)calloc(D,sizeof(float))) == 0) {
- sprintf(errstr, "specanal: can't allocate buffer for Dd\n");
- return(MEMORY_ERROR);
- }
- outframecnt = 0;
- if(is_text_out && normalised) { // is_single_text_out uses this to count no of output windows
- // FIND NORMALISER or COUNT OUTPUT WINDOWS
- if(normalised) {
- fprintf(stdout,"Calculating normalisation factor\n");
- fflush(stdout);
- }
- while(nI < (endsamp + analWinLen)){
- /* prepare for analysis: read next Dd input values */
- memset((char *)sbuf,0,Dd*sizeof(float));
- if((got = fgetfbufEx(sbuf, Dd, dz->ifd[0],0)) < 0) {
- sfperror("specanal: read error");
- return(SYSTEM_ERROR);
- }
- if(outframecnt > 0) {
- zeros = 0;
- for(kk=0;kk < Dd;kk++) {
- if(sbuf[kk] == 0.0)
- zeros++;
- }
- }
- if(got < Dd)
- Dd = got;
- if(!is_single_text_out) {
- sp = sbuf;
- tocp = min(got, input+ibuflen-nextIn);
- got -= tocp;
- while(tocp-- > 0)
- *nextIn++ = *sp++;
- if(got > 0) {
- nextIn -= ibuflen;
- while(got-- > 0)
- *nextIn++ = *sp++;
- }
- if (nextIn >= (input + ibuflen))
- nextIn -= ibuflen;
-
- if (nI > 0) {
- for (i = Dd; i < D; i++){ /* zero fill at EOF */
- *(nextIn++) = 0.0f;
- if (nextIn >= (input + ibuflen))
- nextIn -= ibuflen;
- }
- }
- for (i = 0; i < dz->buflen; i++)
- *(anal + i) = 0.0f; /*initialize*/
- j = (nI - analWinLen - 1 + ibuflen) % ibuflen; /*input pntr*/
- k = nI - analWinLen - 1; /*time shift*/
- while (k < 0)
- k += dz->iparam[SA_CHANS];
- k = k % dz->iparam[SA_CHANS];
- for (i = -analWinLen; i <= analWinLen; i++) { // windowed
- if (++j >= ibuflen)
- j -= ibuflen;
- if (++k >= dz->iparam[SA_CHANS])
- k -= dz->iparam[SA_CHANS];
- *(anal + k) += *(analWindow + i) * *(input + j);
- }
- if((exit_status = fft_(anal,banal,1,N2,1,-2,at,ck,bt,sk,np))<0)
- return(exit_status);
- if((exit_status = reals_(anal,banal,N2,-2))<0)
- return(exit_status);
- if(outframecnt > 0) {
- switch(dz->mode) {
- case(SA_FFT):
- break;
- case(SA_LOGFFT):
- case(SA_CEPSTRUM):
- // Convert to amplitude-phase representation
- for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
- real = *i0;
- imag = *i1;
- mag = (float) sqrt((double)(real * real + imag * imag));
- /* phase unwrapping */
- if (real == 0.0) {
- if(imag==0.0)
- rratio = 0.0;
- else if(imag<0.0)
- rratio = -(PI/2.0);
- else
- rratio = PI/2.0;
- } else {
- rratio = atan((double)imag/(double)real);
- if(real<0.0) {
- if(imag<0.0)
- rratio -= PI;
- else
- rratio += PI;
- }
- }
- phase = (float)rratio;
- *i0 = mag;
- *i1 = phase;
- }
- // Then take log of amplitude ONLY
- for(i=0; i <= N2 * 2; i+=2)
- *(anal + i) = (float)(log(fabs(*(anal + i))));
- if(dz->mode == SA_CEPSTRUM) {
- // Do reconversion to real-imag, similar to PVOC code but without Angle-diff
- for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
- mag = *i0;
- phase = *i1;
- *i0 = (float)((double)mag * cos((double)phase));
- *i1 = (float)((double)mag * sin((double)phase));
- }
- if((exit_status = reals_(anal,banal,N2,2))<0)
- return(exit_status);
- if((exit_status = fft_(anal,banal,1,N2,1,2,at,ck,bt,sk,np))<0)
- return(exit_status);
- for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
- real = *i0;
- imag = *i1;
- mag = (float) sqrt((double)(real * real + imag * imag));
- /* phase unwrapping */
- if (real == 0.0) {
- if(imag==0.0)
- rratio = 0.0;
- else if(imag<0.0)
- rratio = -(PI/2.0);
- else
- rratio = PI/2.0;
- } else {
- rratio = atan((double)imag/(double)real);
- if(real<0.0) {
- if(imag<0.0)
- rratio -= PI;
- else
- rratio += PI;
- }
- }
- phase = (float)rratio;
- *i0 = mag;
- *i1 = phase;
- }
- }
- break;
- case(SA_PVOC):
- case(SA_AVERAGE):
- case(SA_TEMPERED):
- case(SA_HFVARY):
- case(SA_FILTER):
- case(SA_FORMANTS):
- for(i=0,i0=anal,i1=anal+1,oi=oldInPhase; i <= N2; i++,i0+=2,i1+=2,oi++){
- real = *i0;
- imag = *i1;
- *i0 =(float) sqrt((double)(real * real + imag * imag));
- /* phase unwrapping */
- if (*i0 == 0.)
- angleDif = 0.0f;
- else {
- rratio = atan((double)imag/(double)real);
- if(real<0.0) {
- if(imag<0.0)
- rratio -= PI;
- else
- rratio += PI;
- }
- angleDif = (phase = (float)rratio) - *oi;
- *oi = phase;
- }
- if (angleDif > PI)
- angleDif = (float)(angleDif - TWOPI);
- if (angleDif < -PI)
- angleDif = (float)(angleDif + TWOPI);
- /* add in filter center freq.*/
- *i1 = angleDif * RoverTwoPi + ((float) i * F);
- }
- if(dz->mode == SA_FORMANTS) {
- if((exit_status = sa_extract_specenv(anal,dz)) < 0)
- return exit_status;
- }
- break;
- }
- switch(dz->mode) {
- case(SA_FFT): // Output FFT data as channel-centre frq/amp pair
- case(SA_PVOC): // Output PVOC data as frq-amp pair */
- case(SA_LOGFFT):
- case(SA_CEPSTRUM):
- for(kk=0; kk < dz->buflen; kk+= 2) {
- maxsample = max(maxsample,anal[kk]);
- minsample = min(minsample,anal[kk]);
- }
- break;
- case(SA_FORMANTS):
- for(kk=0; kk < dz->infile->specenvcnt; kk++) {
- maxsample = max(maxsample,dz->specenvamp[kk]);
- minsample = min(minsample,dz->specenvamp[kk]);
- }
- break;
- }
- if(curtailed) {
- if(outframecnt == 1) {
- sprintf(errstr,"ERROR: Data in a channel of window at file start is zero, cannot proceed\n");
- return(DATA_ERROR);
- }
- break;
- }
- }
- }
- if(flag /* flag means do this operation only once */
- && (nI > 0) && (Dd < D)){ /* EOF detected */
- flag = 0;
- endsamp = nI + analWinLen - (D - Dd);
- }
- nI += D; /* increment time */
- /* Dd = D except when the end of the sample stream intervenes */
- Dd = min(D, max(0, D+endsamp-nI-analWinLen));
- outframecnt++;
- } /* End of main while loop */
- if(minsample < 0.0)
- offset = -minsample;
- if(flteq(maxsample - minsample,0.0)) {
- sprintf(errstr,"No level found in output data.\n");
- return(DATA_ERROR);
- }
- normaliser = 1.0/(maxsample - minsample);
- outframecnt = 0;
- sndseekEx(dz->ifd[0],0,0);
- nextIn = input;
- nI = -(analWinLen / D) * D;
- Dd = analWinLen + nI + 1;
- flag = 1;
- curtailed = 0;
- endsamp = PA_VERY_BIG_INT;
- }
- while(nI < (endsamp + analWinLen)){
- memset((char *)sbuf,0,Dd*sizeof(float));
- if((got = fgetfbufEx(sbuf, Dd, dz->ifd[0],0)) < 0) {
- sfperror("specanal: read error");
- return(SYSTEM_ERROR);
- }
- if(outframecnt > 0) {
- zeros = 0;
- for(kk=0;kk < Dd;kk++) {
- if(sbuf[kk] == 0.0)
- zeros++;
- }
- if(zeros == Dd) {
- if(dz->mode != SA_AVERAGE && dz->mode != SA_FILTER && dz->mode != SA_TEMPERED && dz->mode != SA_HFVARY) {
- fprintf(stdout,"No Signal at window %d, curtailing analysis here\n",outframecnt);
- fflush(stdout);
- curtailed = 1;
- break;
- }
- }
- }
- if(is_text_out) {
- if(outframecnt > 0) {
- if(outframecnt > 1) // Once first outputfile used
- fclose(dz->fp); // Close it before creating next (last file closed on exit from main)
- strcpy(filename,thisbasnam);
- sprintf(thisnum,"%d",outframecnt);
- strcat(filename,"_"); // Create numbered filename
- strcat(filename,thisnum);
- strcat(filename,thisext);
- if((dz->fp = fopen(filename,"w")) == NULL) {
- sprintf(errstr,"Cannot open output file %s\n", filename);
- return(DATA_ERROR);
- } // Write data to file
- }
- } else if(is_single_text_out) {
- if(outframecnt == 0) {
- strcpy(filename,thisbasnam);
- strcat(filename,thisext);
- if((dz->fp = fopen(filename,"w")) == NULL) {
- sprintf(errstr,"Cannot open output file %s\n", filename);
- return(DATA_ERROR);
- } // Write data to file
- }
- }
- if(got < Dd)
- Dd = got;
- sp = sbuf;
- tocp = min(got, input+ibuflen-nextIn);
- got -= tocp;
- while(tocp-- > 0)
- *nextIn++ = *sp++;
- if(got > 0) {
- nextIn -= ibuflen;
- while(got-- > 0)
- *nextIn++ = *sp++;
- }
- if (nextIn >= (input + ibuflen))
- nextIn -= ibuflen;
- if (nI > 0) {
- for (i = Dd; i < D; i++){ /* zero fill at EOF */
- *(nextIn++) = 0.0f;
- if (nextIn >= (input + ibuflen))
- nextIn -= ibuflen;
- }
- }
- /* ANALYSIS: The analysis subroutine computes the complex output at
- time n of (dz->iparam[SA_CHANS]/2 + 1) of the phase vocoder channels. It operates
- on input samples (n - analWinLen) thru (n + analWinLen) and
- expects to find these in input[(n +- analWinLen) mod ibuflen].
- It expects analWindow to point to the center of a
- symmetric window of length (2 * analWinLen +1). It is the
- responsibility of the main program to ensure that these values
- are correct! The results are returned in anal as succesive
- pairs of real and imaginary values for the lowest (dz->iparam[SA_CHANS]/2 + 1)
- channels. The subroutines fft and reals together implement
- one efficient FFT call for a real input sequence. */
- for (i = 0; i < dz->buflen; i++)
- *(anal + i) = 0.0f; /*initialize*/
- j = (nI - analWinLen - 1 + ibuflen) % ibuflen; /*input pntr*/
- k = nI - analWinLen - 1; /*time shift*/
- while (k < 0)
- k += dz->iparam[SA_CHANS];
- k = k % dz->iparam[SA_CHANS];
- for (i = -analWinLen; i <= analWinLen; i++) {
- if (++j >= ibuflen)
- j -= ibuflen;
- if (++k >= dz->iparam[SA_CHANS])
- k -= dz->iparam[SA_CHANS];
- *(anal + k) += *(analWindow + i) * *(input + j);
- }
- if((exit_status = fft_(anal,banal,1,N2,1,-2,at,ck,bt,sk,np))<0)
- return(exit_status);
- if((exit_status = reals_(anal,banal,N2,-2))<0)
- return(exit_status);
- switch(dz->mode) {
- case(SA_FFT):
- break;
- case(SA_LOGFFT):
- case(SA_CEPSTRUM):
- // Convert to amplitude-phase representation
- for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
- real = *i0;
- imag = *i1;
- mag =(float) sqrt((double)(real * real + imag * imag));
- /* phase unwrapping */
- if (real == 0.0) {
- if(imag == 0.0)
- rratio = 0.0;
- else if(imag<0.0)
- rratio = -(PI/2.0);
- else
- rratio = PI/2.0;
- } else {
- rratio = atan((double)imag/(double)real);
- if(real<0.0) {
- if(imag<0.0)
- rratio -= PI;
- else
- rratio += PI;
- }
- }
- phase = (float)rratio;
- *i0 = mag;
- *i1 = phase;
- }
- // Then take log of amplitude ONLY
- for (i = 0; i <= N2 * 2; i+=2)
- *(anal + i) = (float)(log(fabs(*(anal + i))));
- if(dz->mode == SA_CEPSTRUM) {
- // DO INVERSE conversion to real-imag
- for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
- mag = *i0;
- phase = *i1;
- *i0 = (float)((double)mag * cos((double)phase));
- *i1 = (float)((double)mag * sin((double)phase));
- }
- if((exit_status = reals_(anal,banal,N2,2))<0)
- return(exit_status);
- if((exit_status = fft_(anal,banal,1,N2,1,2,at,ck,bt,sk,np))<0)
- return(exit_status);
- for(i=0,i0=anal,i1=anal+1; i <= N2; i++,i0+=2,i1+=2){
- real = *i0;
- imag = *i1;
- mag = (float) sqrt((double)(real * real + imag * imag));
- /* phase unwrapping */
- if (real == 0.0) {
- if(imag==0.0)
- rratio = 0.0;
- else if(imag<0.0)
- rratio = -(PI/2.0);
- else
- rratio = PI/2.0;
- } else {
- rratio = atan((double)imag/(double)real);
- if(real<0.0) {
- if(imag<0.0)
- rratio -= PI;
- else
- rratio += PI;
- }
- }
- phase = (float)rratio;
- *i0 = mag;
- *i1 = phase;
- }
- }
- break;
- case(SA_PVOC):
- case(SA_AVERAGE):
- case(SA_TEMPERED):
- case(SA_HFVARY):
- case(SA_FILTER):
- case(SA_PVOC_TEST):
- case(SA_FORMANTS):
- /* CONVERSION: The real and imaginary values in anal are converted to
- magnitude and angle-difference-per-second (assuming an
- intermediate sampling rate of rIn) and are returned in
- anal. */
- for(i=0,i0=anal,i1=anal+1,oi=oldInPhase; i <= N2; i++,i0+=2,i1+=2,oi++){
- real = *i0;
- imag = *i1;
- *i0 =(float) sqrt((double)(real * real + imag * imag));
- /* phase unwrapping */
- if (*i0 == 0.)
- angleDif = 0.0f;
- else {
- rratio = atan((double)imag/(double)real);
- if(real<0.0) {
- if(imag<0.0)
- rratio -= PI;
- else
- rratio += PI;
- }
- angleDif = (phase = (float)rratio) - *oi;
- *oi = phase;
- }
- if (angleDif > PI)
- angleDif = (float)(angleDif - TWOPI);
- if (angleDif < -PI)
- angleDif = (float)(angleDif + TWOPI);
- /* add in filter center freq.*/
- *i1 = angleDif * RoverTwoPi + ((float) i * F);
- }
- if(dz->mode == SA_FORMANTS) {
- if((exit_status = sa_extract_specenv(anal,dz)) < 0)
- return exit_status;
- }
- break;
- }
- if(outframecnt == 0) {
- switch(dz->mode) {
- case(SA_PVOC_TEST):
- if((exit_status = write_samps_pvoc(anal, dz->buflen, dz)) < 0)
- return(exit_status);
- break;
- }
- } else {
- switch(dz->mode) {
- case(SA_FFT): // Output FFT data as channel-centre frq/amp pair
- case(SA_LOGFFT):
- case(SA_CEPSTRUM):
- centrefrq = 0.0;
- for(kk=0; kk < dz->buflen; kk+= 2) {
- level = anal[kk];
- if(normalised)
- level = (level + offset) * normaliser;
- if(fprintf(dz->fp,"%f\t%f\n",(float)centrefrq,(float)level)<2) {
- sprintf(errstr,"Problem writing FFT data to file %s\n",filename);
- return(PROGRAM_ERROR);
- }
- centrefrq += dz->chwidth;
- // HEREH: IS THIS THE CORRECT CALCULATION FOR centrefrq
- }
- break;
- case(SA_PVOC): // Output PVOC data as frq-amp pair */
- if(ordered) {
- for(kk=0; kk < dz->buflen-2; kk+= 2) { // Force frq values into ascending order
- kfrq = anal[kk+1]; // So output will display as a brkpnt
- for(jj=kk + 2;jj < dz->buflen;jj += 2) {
- jfrq = anal[jj+1];
- if(jfrq < kfrq) {
- temp = anal[kk+1];
- anal[kk+1] = anal[jj+1];
- anal[jj+1] = temp;
- temp = anal[kk];
- anal[kk] = anal[jj];
- anal[jj] = temp;
- kfrq = jfrq;
- }
- }
- }
- }
- for(kk=0; kk < dz->buflen; kk+= 2) {
- level = anal[kk];
- if(normalised)
- level = (level + offset) * normaliser;
- if(fprintf(dz->fp,"%f\t%f\n",anal[kk+1],(float)level)<2) {
- sprintf(errstr,"Problem writing PVOC data to file %s\n",filename);
- return(PROGRAM_ERROR);
- }
- }
- break;
- case(SA_AVERAGE): // Sum PVOC amplitude in semitonal bins */
- case(SA_TEMPERED):
- case(SA_HFVARY):
- case(SA_FILTER):
- if(dz->mode == SA_TEMPERED) {
- if(outframecnt % dz->framecnt == 0) {
- if((exit_status = get_tempered_pitch(averages,averages2,averages3,dz)) < 0)
- return exit_status;
- }
- } else if(dz->mode == SA_HFVARY) {
- if(outframecnt % dz->framecnt == 0) {
- if((exit_status = get_tempered_hf(averages,averages2,averages3,dz)) < 0)
- return exit_status;
- }
- }
- for(kk=0; kk < dz->buflen; kk+= 2) {
- frq = anal[kk+1];
- level = anal[kk];
- for(jj=0;jj < 256; jj+=2) {
- if(frq < averages[jj]) {
- averages[jj+1] = (float)(averages[jj+1] + level);
- break;
- }
- }
- if(jj >= 256)
- averages[jj+1] = (float)(averages[jj+1] + level);
- }
- break;
- case(SA_FORMANTS): // Output FORMANTS data */
- for(kk=0; kk < dz->infile->specenvcnt; kk++) {
- level = dz->specenvamp[kk];
- if(normalised)
- level = (level + offset) * normaliser;
- if(fprintf(dz->fp,"%f\t%f\n",dz->specenvfrq[kk],(float)level)<2) {
- sprintf(errstr,"Problem writing PVOC data to file %s\n",filename);
- return(PROGRAM_ERROR);
- }
- }
- break;
- case(SA_PVOC_TEST):
- if((exit_status = write_samps_pvoc(anal, dz->buflen, dz)) < 0)
- return(exit_status);
- break;
- }
- }
- if(curtailed) {
- if(is_text_out || (is_single_text_out && (outframecnt == 1))) {
- fclose(dz->fp);
- if(remove(filename) < 0) {
- fprintf(stdout, "ERROR: Can't delete output textfile %s\n",filename);
- fflush(stdout);
- }
- dz->process_type = OTHER_PROCESS; // prevents CDP trying to close non-existent file
- }
- if(outframecnt == 1) {
- fprintf(stdout,"ERROR: Data in window at file start is zero, cannot proceed\n");
- fflush(stdout);
- return(DATA_ERROR);
- }
- break;
- }
- if(flag /* flag means do this operation only once */
- && (nI > 0) && (Dd < D)){ /* EOF detected */
- flag = 0;
- endsamp = nI + analWinLen - (D - Dd);
- }
- nI += D; /* increment time */
- /* Dd = D except when the end of the sample stream intervenes */
- Dd = min(D, max(0, D+endsamp-nI-analWinLen));
- outframecnt++;
- } /* End of main while loop */
- switch(dz->mode) {
- case(SA_AVERAGE): // Output average semitone-amplitude data
- case(SA_FILTER):
- maxsample = 0.0;
- minsample = 0.0;
- for(kk=0; kk < 258; kk+=2) {
- minsample = min(averages[kk+1],minsample);
- maxsample = max(averages[kk+1],maxsample);
- }
- range = maxsample - minsample;
- if(flteq(range,0.0)) {
- sprintf(errstr,"No significant signal found in input sound.\n");
- return(DATA_ERROR);
- }
- for(jj = 0, kk=0; jj < BINCNT; kk+=2, jj++) {
- if(kk == 0)
- averages[kk] = (float)(miditohz(0)/2.0); // i.e. anything below midi zero
- else
- averages[kk] = (float)(miditohz(jj-1)); // i.e. anything around midi jj-1
- averages[kk+1] = (float)((averages[kk+1] - minsample)/range);
- }
- averages[256] = (float)miditohz(127); // i.e. anything at or above midi 127
- averages[257] = (float)((averages[257] - minsample)/range);
- switch(dz->mode) {
- case(SA_AVERAGE):
- for(jj=1,kk=2; jj < BINCNT; jj++, kk+=2) { // Ignore pitches below MIDI 0
- if(fprintf(dz->fp,"%d\t%f\n",(int)round(unchecked_hztomidi(averages[kk])),averages[kk+1])<1) {
- sprintf(errstr,"Problem writing average semitone amplitude data to file %s\n",filename);
- return(PROGRAM_ERROR);
- }
- }
- break;
- case(SA_FILTER):
- for(n = 0; n < BINCNT; n++) { // For every peak-numbering
- maxval = -10000;
- maxpos = 0;
- // For every semitone bin
- for(jj = 0, kk= 0; jj < BINCNT; jj++, kk+=2) {
- doskip = 0;
- if(n>0) {
- for(qq=0;qq<n;qq++) { // If this bin is already a peak
- if(peaks[qq] == jj) {
- doskip = 1;
- break;
- }
- }
- }
- if(doskip)
- continue;
- if(averages[kk+1] > maxval) { // is it the loudest non-listed peak??
- maxval = averages[kk+1];
- maxpos = jj;
- }
- }
- peaks[n] = maxpos; // peaks[n] takes the number of loudest peak amongst those not yet listed
- // peaks array thus becomes listing of peaks in descending loudness order
- }
- for(n = 0; n < BINCNT; n++) { // Move peak at MIDI zero to bottom of peaks list
- if(peaks[n] == 0) {
- for(qq=n+1;qq<BINCNT;qq++)
- peaks[qq-1] = peaks[qq];
- peaks[BINCNT-1] = 0;
- break;
- }
- }
- // If flag set, eliminate peaks a semitone away from more prominent peaks
- if(dz->vflag[SA_DECHROM]) {
- for(q = 0; q < BINCNT; q++) { // For ALL peaks, starting at the loudest
- jj = peaks[q];
- kk = jj*2; // Find the associated frq-amp data
- if(averages[kk] < miditohz(0)) // (if frequency is below midi 0, keep)
- continue;
- peakmidi = (int)round(unchecked_hztomidi(averages[kk])); // Get the midipitch of this peak
- qq = 0;
- chromcnt = 0;
- while(qq < BINCNT) { // Compare this peak with all other peaks
- if(qq != q) {
- jj = peaks[qq];
- kk = jj*2; // If other pitch is a semitone higher or lower
- if((averages[kk] >= 0.0) && (abs((int)round(unchecked_hztomidi(averages[kk])) - peakmidi) == 1)) {
- averages[kk] = -1.0; // Flag less-prominent peak as not-wanted, by setting frq to -1
- for(n=qq+1;n < BINCNT;n++)
- peaks[n-1] = peaks[n]; // Shuffle-down overwrite peak-data (peak eliminated from list)
- peaks[BINCNT-1] = jj; // Eliminated peak goes to bottom of list of peaks
- if(++chromcnt > 1) // No more than 2 semitone-adjacent peaks, so if got 2, drop from inner loop
- break;
- qq--;
- }
- }
- qq++;
- }
- }
- }
- filtercnt = 0;
- if(dz->vflag[SA_NO_HARMONICS]) { // If flag set, eliminate harmonics of peaks, starting at most prominent peak
- do {
- harmonic_amongst_loudest_peaks = 0;
- for(q = 0; q < dz->iparam[SA_PKCNT]; q++) { // For SA_PKCNT peaks, starting at the loudest
- jj = peaks[q];
- kk = jj*2; // Find the associated frq-amp data
- if(flteq(averages[kk],-1.0)) { // If this peak (and hence all the remaining peaks) has already been rejected,
- filtercnt = q; // reset filtercnt and quit.
- break;
- }
- if(averages[kk] < miditohz(0)) // (if frequency is below midi 0, keep)
- continue;
- peakfrq = averages[kk];
- qq = 0;
- while(qq < BINCNT) { // Compare this peak with all other peaks
- if(qq != q) {
- jj = peaks[qq];
- kk = jj*2; // If higher frequency is a harmonic of lower
- if((averages[kk] >= 0.0) && is_a_harmonic_x(averages[kk],peakfrq)) {
- averages[kk] = -1.0; // Flag peak as not-wanted, by setting frq to -1
- for(n=qq+1;n < BINCNT;n++)
- peaks[n-1] = peaks[n]; // Shuffle-down overwrite peak-data (peak eliminated from list)
- peaks[BINCNT-1] = jj; // Eliminated peak goes to bottom of list of peaks
- if(qq < dz->iparam[SA_PKCNT]) // If we have thus eliminated one of the currently loudest SA_PKCNT peaks
- harmonic_amongst_loudest_peaks = 1;
- // Flag that a new search for harmonics is needed, with the new set of SA_PKCNT peaks
- qq--;
- }
- }
- qq++;
- }
- }
- } while(harmonic_amongst_loudest_peaks);
- }
- if(filtercnt == 0) { // If filtercnt has not been reset previously, set it now
- filtercnt = dz->iparam[SA_PKCNT];
- for(n=filtercnt;n < BINCNT;n++) {
- jj = peaks[n];
- kk = jj*2;
- averages[kk] = -1.0; // and set all unwanted peaks to -1
- }
- }
- jj = 0;
- bincnt = BINCNT;
- while(jj < bincnt-1) { // Peaks set to -1 are eliminated by downward-shuffle overwrite
- kk = jj*2;
- if(averages[kk] < 0) {
- for(n = kk;n < (bincnt-1)*2; n++)
- averages[n] = averages[n+2];
- bincnt--;
- } else
- jj++;
- }
- kk = jj*2;
- if(averages[kk] < 0)
- bincnt--;
- if(bincnt != filtercnt) {
- sprintf(errstr,"Error in bin-elimination logic. bincnt = %d filtercnt = %d\n",bincnt,filtercnt);
- return PROGRAM_ERROR;
- }
- // Convert to MIDI
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2)
- averages[kk] = (float)((int)round(unchecked_hztomidi(averages[kk])));
- // Do any transposition required
- if(dz->vflag[SA_DDOWNOCT]) {
- downtranspos = 1;
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
- if(averages[kk] - 12.0 < 0) {
- downtranspos = 0;
- break;
- }
- }
- if(!downtranspos) {
- fprintf(stdout,"WARNING: OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
- fflush(stdout);
- } else {
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2)
- averages[kk] -= 12.0;
- }
- } else if(dz->vflag[SA_DDOWN2OCT]) {
- downtranspos = 2;
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
- if(averages[kk] - 24.0 < 0) {
- downtranspos = 0;
- break;
- }
- }
- if(!downtranspos) {
- fprintf(stdout,"WARNING: TWO OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
- fflush(stdout);
- } else {
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2)
- averages[kk] -= 24.0;
- }
- }
- if(dz->vflag[SA_IGNORE_AMP]) { // Ignore amplitudes (set them all to 1.0)
- for(jj=0,kk=1;jj < filtercnt;jj++,kk+=2)
- averages[kk] = 1.0;
- }
- if(dz->vflag[SA_MIDILIST]) {
- sprintf(tempstr,"");
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
- if((int)round(averages[kk]) >= 0) {
- sprintf(tempstr2,"%d\t",(int)round(averages[kk]));
- strcat(tempstr,tempstr2);
- }
- }
- } else {
- sprintf(tempstr,"0.0\t");
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
- sprintf(tempstr2,"%d\t%f\t",(int)round(averages[kk]),averages[kk+1]);
- strcat(tempstr,tempstr2);
- }
- if(fprintf(dz->fp,"%s\n",tempstr)<1) {
- sprintf(errstr,"Problem writing filter data to file %s\n",filename);
- return(PROGRAM_ERROR);
- }
- sprintf(tempstr,"10000.0\t");
- for(jj = 0,kk=0;jj < filtercnt;jj++,kk+=2) {
- sprintf(tempstr2,"%d\t%f\t",(int)round(averages[kk]),averages[kk+1]);
- strcat(tempstr,tempstr2);
- }
- }
- if(fprintf(dz->fp,"%s\n",tempstr)<1) {
- sprintf(errstr,"Problem writing filter data to file %s\n",filename);
- return(PROGRAM_ERROR);
- }
- break;
- }
- break;
- case(SA_TEMPERED):
- if(outframecnt % dz->framecnt > 0) { // Extract pitch from any part-window at end
- if((exit_status = get_tempered_pitch(averages,averages2,averages3,dz)) < 0)
- return exit_status;
- }
- if((exit_status = smooth_and_output_tempered_pitch(dz))<0)
- return exit_status;
- break;
- case(SA_HFVARY):
- if(outframecnt % dz->framecnt > 0) { // Extract HF from any part-window at end
- if((exit_status = get_tempered_hf(averages,averages2,averages3,dz)) < 0)
- return exit_status;
- }
- if((exit_status = smooth_and_output_varying_hf(dz))<0)
- return exit_status;
- break;
- }
- return(FINISHED);
- }
- /************************************ SNDWRITE_HEADER ************************************/
- int sndwrite_header(int N2,int *Nchans,float *arate,float R,int D,int origsize,int *isr,int M,dataptr dz)
- {
- *Nchans = dz->iparam[SA_CHANS] + 2;
- dz->outfile->channels = *Nchans;
- *arate = (float)(R/(float)D);
- dz->outfile->srate = (int)(*arate);
- dz->outfile->arate = *arate;
- dz->outfile->origstype = origsize;
- dz->outfile->origrate = *isr;
- dz->outfile->Mlen = M;
- dz->outfile->Dfac = D;
- fflush(stdout);
- return(FINISHED);
- }
- /******************************* WRITE_SAMPS_PVOC ********************************/
- int write_samps_pvoc(float *bbuf,int samps_to_write,dataptr dz)
- {
-
- int samps_written;
- int i,j;
- int granularity = 22100;
- int this_granularity = 0;
- float val;
- if(dz->needpeaks){
- for(i=0;i < samps_to_write; i += dz->outchans){
- for(j = 0;j < dz->outchans;j++){
- val = (float)fabs(bbuf[i+j]);
- /* this way, posiiton of first peak value is stored */
- if(val > dz->outpeaks[j].value){
- dz->outpeaks[j].value = val;
- dz->outpeaks[j].position = dz->outpeakpos[j];
- }
- }
- /* count framepos */
- for(j=0;j < dz->outchans;j++)
- dz->outpeakpos[j]++;
- }
- }
- if((samps_written = fputfbufEx(bbuf,samps_to_write,dz->ofd))<=0) {
- sprintf(errstr,"Can't write to output soundfile: %s\n",sferrstr());
- return(SYSTEM_ERROR);
- }
- dz->total_samps_written += samps_written;
- this_granularity += samps_to_write;
- if(this_granularity > granularity){
- display_virtual_time(dz->total_samps_written,dz);
- this_granularity -= granularity;
- }
- return(FINISHED);
- }
- ///////////// MXFFT
- /*
- *-----------------------------------------------------------------------
- * subroutine: fft
- * multivariate complex fourier transform, computed in place
- * using mixed-radix fast fourier transform algorithm.
- *-----------------------------------------------------------------------
- *
- * this is the call from C:
- * fft_(anal,banal,&one,&N2,&one,&mtwo);
- * CHANGED TO:-
- * fft_(anal,banal,one,N2,one,mtwo);
- */
- int fft_(float *a, float *b, int nseg, int n, int nspn, int isn,float *at,float *ck,float *bt,float *sk,int *np)
- /* a: pointer to array 'anal' */
- /* b: pointer to array 'banal' */
- {
- int exit_status;
- int nfac[16]; /* These are one bigger than needed */
- /* because wish to use Fortran array */
- /* index which runs 1 to n, not 0 to n */
- int m = 0, nf, k, kt, ntot, j, jj, maxf /*, maxp=0*/;
- /* work space pointers */
- // float *at, *ck, *bt, *sk;
- // int *np;
- /* reduce the pointers to input arrays - by doing this, FFT uses FORTRAN
- indexing but retains compatibility with C arrays */
- a--; b--;
- /*
- * determine the factors of n
- */
- k=nf=abs(n);
- if(nf==1)
- return(FINISHED);
- nspn=abs(nf*nspn);
- ntot=abs(nspn*nseg);
- if(isn*ntot == 0){
- sprintf(errstr,"zero in FFT parameters %d %d %d %d",nseg, n, nspn, isn);
- return(DATA_ERROR);
- }
- for (m=0; !(k%16); nfac[++m]=4,k/=16);
- for (j=3,jj=9; jj<=k; j+=2,jj=j*j)
- for (; !(k%jj); nfac[++m]=j,k/=jj);
- if (k<=4) {
- kt = m;
- nfac[m+1] = k;
- if(k != 1)
- m++;
- } else {
- if(k%4==0){
- nfac[++m]=2;
- k/=4;
- }
- kt = m;
- // maxp = max((kt+kt+2),(k-1));
- for(j=2; j<=k; j=1+((j+1)/2)*2) {
- if(k%j==0){
- nfac[++m]=j;
- k/=j;
- }
- }
- }
- // if(m <= kt+1)
- // maxp = m + kt + 1;
- if(m+kt > 15) {
- sprintf(errstr,"FFT parameter n has more than 15 factors : %d", n);
- return(DATA_ERROR);
- }
- if(kt!=0) {
- j = kt;
- while(j)
- nfac[++m]=nfac[j--];
- }
- maxf = nfac[m-kt];
- if(kt > 0)
- maxf = max(nfac[kt],maxf);
- /* allocate workspace - assume no errors! */
- // at = (float *) calloc(maxf,sizeof(float));
- // ck = (float *) calloc(maxf,sizeof(float));
- // bt = (float *) calloc(maxf,sizeof(float));
- // sk = (float *) calloc(maxf,sizeof(float));
- // np = (int *) calloc(maxp,sizeof(int));
- /* decrement pointers to allow FORTRAN type usage in fftmx */
- at--; bt--; ck--; sk--; np--;
- /* call fft driver */
- if((exit_status = fftmx(a,b,ntot,nf,nspn,isn,m,&kt,at,ck,bt,sk,np,nfac))<0)
- return(exit_status);
- /* restore pointers before releasing */
- at++; bt++; ck++; sk++; np++;
- /* release working storage before returning - assume no problems */
- // (void) free(at);
- // (void) free(sk);
- // (void) free(bt);
- // (void) free(ck);
- // (void) free(np);
- return(FINISHED);
- }
- /*
- *-----------------------------------------------------------------------
- * subroutine: fftmx
- * called by subroutine 'fft' to compute mixed-radix fourier transform
- *-----------------------------------------------------------------------
- */
- 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[])
- {
- int i,inc,
- j,jc,jf, jj,
- k, k1, k2, k3=0, k4,
- kk,klim,ks,kspan, kspnn,
- lim,
- maxf,mm,
- nn,nt;
- double aa, aj, ajm, ajp, ak, akm, akp,
- bb, bj, bjm, bjp, bk, bkm, bkp,
- c1, c2=0.0, c3=0.0, c72, cd,
- dr,
- rad,
- sd, s1, s2=0.0, s3=0.0, s72, s120;
- double xx; /****** ADDED APRIL 1991 *********/
- inc=abs(isn);
- nt = inc*ntot;
- ks = inc*nspan;
- /******************* REPLACED MARCH 29: ***********************
- rad = atan((double)1.0);
- **************************************************************/
- rad = 0.785398163397448278900;
- /******************* REPLACED MARCH 29: ***********************
- s72 = rad/0.625;
- c72 = cos(s72);
- s72 = sin(s72);
- **************************************************************/
- c72 = 0.309016994374947451270;
- s72 = 0.951056516295153531190;
- /******************* REPLACED MARCH 29: ***********************
- s120 = sqrt((double)0.75);
- **************************************************************/
- s120 = 0.866025403784438707600;
- /* scale by 1/n for isn > 0 ( reverse transform ) */
- if (isn < 0){
- s72 = -s72;
- s120 = -s120;
- rad = -rad;}
- else{ ak = 1.0/(double)n;
- for(j=1; j<=nt;j += inc){
- a[j] = (float)(a[j] * ak);
- b[j] = (float)(b[j] * ak);
- }
- }
- kspan = ks;
- nn = nt - inc;
- jc = ks/n;
- /* sin, cos values are re-initialized each lim steps */
- lim = 32;
- klim = lim * jc;
- i = 0;
- jf = 0;
- maxf = m - (*kt);
- maxf = nfac[maxf];
- if((*kt) > 0)
- maxf = max(nfac[*kt],maxf);
- /*
- * compute fourier transform
- */
- lbl40:
- dr = (8.0 * (double)jc)/((double)kspan);
- /*************************** APRIL 1991 POW & POW2 not WORKING.. REPLACE *******
- cd = 2.0 * (pow2 ( sin((double)0.5 * dr * rad)) );
- *******************************************************************************/
- xx = sin((double)0.5 * dr * rad);
- cd = 2.0 * xx * xx;
- sd = sin(dr * rad);
- kk = 1;
- if(nfac[++i]!=2) goto lbl110;
- /*
- * transform for factor of 2 (including rotation factor)
- */
- kspan /= 2;
- k1 = kspan + 2;
- do{ do{ k2 = kk + kspan;
- ak = a[k2];
- bk = b[k2];
- a[k2] = (float)((a[kk]) - ak);
- b[k2] = (float)((b[kk]) - bk);
- a[kk] = (float)((a[kk]) + ak);
- b[kk] = (float)((b[kk]) + bk);
- kk = k2 + kspan;
- } while(kk <= nn);
- kk -= nn;
- }while(kk <= jc);
- if(kk > kspan) goto lbl350;
- lbl60: c1 = 1.0 - cd;
- s1 = sd;
- mm = min((k1/2),klim);
- goto lbl80;
- lbl70: ak = c1 - ((cd*c1)+(sd*s1));
- s1 = ((sd*c1)-(cd*s1)) + s1;
- c1 = ak;
- lbl80: do{ do{ k2 = kk + kspan;
- ak = a[kk] - a[k2];
- bk = b[kk] - b[k2];
- a[kk] = a[kk] + a[k2];
- b[kk] = b[kk] + b[k2];
- a[k2] = (float)((c1 * ak) - (s1 * bk));
- b[k2] = (float)((s1 * ak) + (c1 * bk));
- kk = k2 + kspan;
- }while(kk < nt);
- k2 = kk - nt;
- c1 = -c1;
- kk = k1 - k2;
- }while(kk > k2);
- kk += jc;
- if(kk <= mm) goto lbl70;
- if(kk < k2) goto lbl90;
- k1 += (inc + inc);
- kk = ((k1-kspan)/2) + jc;
- if(kk <= (jc+jc)) goto lbl60;
- goto lbl40;
- lbl90: s1 = ((double)((kk-1)/jc)) * dr * rad;
- c1 = cos(s1);
- s1 = sin(s1);
- mm = min( k1/2, mm+klim);
- goto lbl80;
- /*
- * transform for factor of 3 (optional code)
- */
- lbl100: k1 = kk + kspan;
- k2 = k1 + kspan;
- ak = a[kk];
- bk = b[kk];
- aj = a[k1] + a[k2];
- bj = b[k1] + b[k2];
- a[kk] = (float)(ak + aj);
- b[kk] = (float)(bk + bj);
- ak += (-0.5 * aj);
- bk += (-0.5 * bj);
- aj = (a[k1] - a[k2]) * s120;
- bj = (b[k1] - b[k2]) * s120;
- a[k1] = (float)(ak - bj);
- b[k1] = (float)(bk + aj);
- a[k2] = (float)(ak + bj);
- b[k2] = (float)(bk - aj);
- kk = k2 + kspan;
- if(kk < nn) goto lbl100;
- kk -= nn;
- if(kk <= kspan) goto lbl100;
- goto lbl290;
- /*
- * transform for factor of 4
- */
- lbl110: if(nfac[i] != 4) goto lbl230;
- kspnn = kspan;
- kspan = kspan/4;
- lbl120: c1 = 1.0;
- s1 = 0;
- mm = min( kspan, klim);
- goto lbl150;
- lbl130: c2 = c1 - ((cd*c1)+(sd*s1));
- s1 = ((sd*c1)-(cd*s1)) + s1;
- /*
- * the following three statements compensate for truncation
- * error. if rounded arithmetic is used, substitute
- * c1=c2
- *
- * c1 = (0.5/(pow2(c2)+pow2(s1))) + 0.5;
- * s1 = c1*s1;
- * c1 = c1*c2;
- */
- c1 = c2;
- lbl140: c2 = (c1 * c1) - (s1 * s1);
- s2 = c1 * s1 * 2.0;
- c3 = (c2 * c1) - (s2 * s1);
- s3 = (c2 * s1) + (s2 * c1);
- lbl150: k1 = kk + kspan;
- k2 = k1 + kspan;
- k3 = k2 + kspan;
- akp = a[kk] + a[k2];
- akm = a[kk] - a[k2];
- ajp = a[k1] + a[k3];
- ajm = a[k1] - a[k3];
- a[kk] = (float)(akp + ajp);
- ajp = akp - ajp;
- bkp = b[kk] + b[k2];
- bkm = b[kk] - b[k2];
- bjp = b[k1] + b[k3];
- bjm = b[k1] - b[k3];
- b[kk] = (float)(bkp + bjp);
- bjp = (float)(bkp - bjp);
- if(isn < 0) goto lbl180;
- akp = akm - bjm;
- akm = akm + bjm;
- bkp = bkm + ajm;
- bkm = bkm - ajm;
- if(s1 == 0.0) goto lbl190;
- lbl160: a[k1] = (float)((akp*c1) - (bkp*s1));
- b[k1] = (float)((akp*s1) + (bkp*c1));
- a[k2] = (float)((ajp*c2) - (bjp*s2));
- b[k2] = (float)((ajp*s2) + (bjp*c2));
- a[k3] = (float)((akm*c3) - (bkm*s3));
- b[k3] = (float)((akm*s3) + (bkm*c3));
- kk = k3 + kspan;
- if(kk <= nt) goto lbl150;
- lbl170: kk -= (nt - jc);
- if(kk <= mm) goto lbl130;
- if(kk < kspan) goto lbl200;
- kk -= (kspan - inc);
- if(kk <= jc) goto lbl120;
- if(kspan==jc) goto lbl350;
- goto lbl40;
- lbl180: akp = akm + bjm;
- akm = akm - bjm;
- bkp = bkm - ajm;
- bkm = bkm + ajm;
- if(s1 != 0.0) goto lbl160;
- lbl190: a[k1] = (float)akp;
- b[k1] = (float)bkp;
- a[k2] = (float)ajp;
- b[k2] = (float)bjp;
- a[k3] = (float)akm;
- b[k3] = (float)bkm;
- kk = k3 + kspan;
- if(kk <= nt) goto lbl150;
- goto lbl170;
- lbl200: s1 = ((double)((kk-1)/jc)) * dr * rad;
- c1 = cos(s1);
- s1 = sin(s1);
- mm = min( kspan, mm+klim);
- goto lbl140;
- /*
- * transform for factor of 5 (optional code)
- */
- lbl210: c2 = (c72*c72) - (s72*s72);
- s2 = 2.0 * c72 * s72;
- lbl220: k1 = kk + kspan;
- k2 = k1 + kspan;
- k3 = k2 + kspan;
- k4 = k3 + kspan;
- akp = a[k1] + a[k4];
- akm = a[k1] - a[k4];
- bkp = b[k1] + b[k4];
- bkm = b[k1] - b[k4];
- ajp = a[k2] + a[k3];
- ajm = a[k2] - a[k3];
- bjp = b[k2] + b[k3];
- bjm = b[k2] - b[k3];
- aa = a[kk];
- bb = b[kk];
- a[kk] = (float)(aa + akp + ajp);
- b[kk] = (float)(bb + bkp + bjp);
- ak = (akp*c72) + (ajp*c2) + aa;
- bk = (bkp*c72) + (bjp*c2) + bb;
- aj = (akm*s72) + (ajm*s2);
- bj = (bkm*s72) + (bjm*s2);
- a[k1] = (float)(ak - bj);
- a[k4] = (float)(ak + bj);
- b[k1] = (float)(bk + aj);
- b[k4] = (float)(bk - aj);
- ak = (akp*c2) + (ajp*c72) + aa;
- bk = (bkp*c2) + (bjp*c72) + bb;
- aj = (akm*s2) - (ajm*s72);
- bj = (bkm*s2) - (bjm*s72);
- a[k2] = (float)(ak - bj);
- a[k3] = (float)(ak + bj);
- b[k2] = (float)(bk + aj);
- b[k3] = (float)(bk - aj);
- kk = k4 + kspan;
- if(kk < nn) goto lbl220;
- kk -= nn;
- if(kk <= kspan) goto lbl220;
- goto lbl290;
- /*
- * transform for odd factors
- */
- lbl230: k = nfac[i];
- kspnn = kspan;
- kspan /= k;
- if(k==3) goto lbl100;
- if(k==5) goto lbl210;
- if(k==jf) goto lbl250;
- jf = k;
- s1 = rad/(((double)(k))/8.0);
- c1 = cos(s1);
- s1 = sin(s1);
- ck[jf] = 1.0f;
- sk[jf] = 0.0f;
- for(j=1; j<k ; j++){
- ck[j] = (float)((ck[k])*c1 + (sk[k])*s1);
- sk[j] = (float)((ck[k])*s1 - (sk[k])*c1);
- k--;
- ck[k] = ck[j];
- sk[k] = -(sk[j]);
- }
- lbl250: k1 = kk;
- k2 = kk + kspnn;
- aa = a[kk];
- bb = b[kk];
- ak = aa;
- bk = bb;
- j = 1;
- k1 += kspan;
- do{ k2 -= kspan;
- j++;
- at[j] = a[k1] + a[k2];
- ak = at[j] + ak;
- bt[j] = b[k1] + b[k2];
- bk = bt[j] + bk;
- j++;
- at[j] = a[k1] - a[k2];
- bt[j] = b[k1] - b[k2];
- k1 += kspan;
- }while(k1 < k2);
- a[kk] = (float)ak;
- b[kk] = (float)bk;
- k1 = kk;
- k2 = kk + kspnn;
- j = 1;
- lbl270: k1 += kspan;
- k2 -= kspan;
- jj = j;
- ak = aa;
- bk = bb;
- aj = 0.0;
- bj = 0.0;
- k = 1;
- do{ k++;
- ak = (at[k] * ck[jj]) + ak;
- bk = (bt[k] * ck[jj]) + bk;
- k++;
- aj = (at[k] * sk[jj]) + aj;
- bj = (bt[k] * sk[jj]) + bj;
- jj += j;
- if (jj > jf)
- jj -= jf;
- }while(k < jf);
- k = jf - j;
- a[k1] = (float)(ak - bj);
- b[k1] = (float)(bk + aj);
- a[k2] = (float)(ak + bj);
- b[k2] = (float)(bk - aj);
- j++;
- if(j < k) goto lbl270;
- kk += kspnn;
- if(kk <= nn) goto lbl250;
- kk -= nn;
- if(kk<=kspan) goto lbl250;
- /*
- * multiply by rotation factor (except for factors of 2 and 4)
- */
- lbl290: if(i==m) goto lbl350;
- kk = jc + 1;
- lbl300: c2 = 1.0 - cd;
- s1 = sd;
- mm = min( kspan, klim);
- goto lbl320;
- lbl310: c2 = c1 - ((cd*c1) + (sd*s1));
- s1 = s1 + ((sd*c1) - (cd*s1));
- lbl320: c1 = c2;
- s2 = s1;
- kk += kspan;
- lbl330: ak = a[kk];
- a[kk] = (float)((c2*ak) - (s2 * b[kk]));
- b[kk] = (float)((s2*ak) + (c2 * b[kk]));
- kk += kspnn;
- if(kk <= nt) goto lbl330;
- ak = s1*s2;
- s2 = (s1*c2) + (c1*s2);
- c2 = (c1*c2) - ak;
- kk -= (nt - kspan);
- if(kk <= kspnn) goto lbl330;
- kk -= (kspnn - jc);
- if(kk <= mm) goto lbl310;
- if(kk < kspan) goto lbl340;
- kk -= (kspan - jc - inc);
- if(kk <= (jc+jc)) goto lbl300;
- goto lbl40;
- lbl340: s1 = ((double)((kk-1)/jc)) * dr * rad;
- c2 = cos(s1);
- s1 = sin(s1);
- mm = min( kspan, mm+klim);
- goto lbl320;
- /*
- * permute the results to normal order---done in two stages
- * permutation for square factors of n
- */
- lbl350: np[1] = ks;
- if (!(*kt)) goto lbl440;
- k = *kt + *kt + 1;
- if(m < k)
- k--;
- np[k+1] = jc;
- for(j=1; j < k; j++,k--){
- np[j+1] = np[j] / nfac[j];
- np[k] = np[k+1] * nfac[j];
- }
- k3 = np[k+1];
- kspan = np[2];
- kk = jc + 1;
- k2 = kspan + 1;
- j = 1;
- if(n != ntot) goto lbl400;
- /*
- * permutation for single-variate transform (optional code)
- */
- lbl370: do{ ak = a[kk];
- a[kk] = a[k2];
- a[k2] = (float)ak;
- bk = b[kk];
- b[kk] = b[k2];
- b[k2] = (float)bk;
- kk += inc;
- k2 += kspan;
- }while(k2 < ks);
- lbl380: do{ k2 -= np[j++];
- k2 += np[j+1];
- }while(k2 > np[j]);
- j = 1;
- lbl390: if(kk < k2){
- goto lbl370;
- }
- kk += inc;
- k2 += kspan;
- if(k2 < ks) goto lbl390;
- if(kk < ks) goto lbl380;
- jc = k3;
- goto lbl440;
- /*
- * permutation for multivariate transform
- */
- lbl400: do{ do{ k = kk + jc;
- do{ ak = a[kk];
- a[kk] = a[k2];
- a[k2] = (float)ak;
- bk = b[kk];
- b[kk] = b[k2];
- b[k2] = (float)bk;
- kk += inc;
- k2 += inc;
- }while(kk < k);
- kk += (ks - jc);
- k2 += (ks - jc);
- }while(kk < nt);
- k2 -= (nt - kspan);
- kk -= (nt - jc);
- }while(k2 < ks);
- lbl420: do{ k2 -= np[j++];
- k2 += np[j+1];
- }while(k2 > np[j]);
- j = 1;
- lbl430: if(kk < k2) goto lbl400;
- kk += jc;
- k2 += kspan;
- if(k2 < ks) goto lbl430;
- if(kk < ks) goto lbl420;
- jc = k3;
- lbl440: if((2*(*kt))+1 >= m)
- return(FINISHED);
- kspnn = *(np + *(kt) + 1);
- j = m - *kt;
- nfac[j+1] = 1;
- lbl450: nfac[j] = nfac[j] * nfac[j+1];
- j--;
- if(j != *kt) goto lbl450;
- *kt = *(kt) + 1;
- nn = nfac[*kt] - 1;
- jj = 0;
- j = 0;
- goto lbl480;
- lbl460: jj -= k2;
- k2 = kk;
- kk = nfac[++k];
- lbl470: jj += kk;
- if(jj >= k2) goto lbl460;
- np[j] = jj;
- lbl480: k2 = nfac[*kt];
- k = *kt + 1;
- kk = nfac[k];
- j++;
- if(j <= nn) goto lbl470;
- /* Determine permutation cycles of length greater than 1 */
- j = 0;
- goto lbl500;
- lbl490: k = kk;
- kk = np[k];
- np[k] = -kk;
- if(kk != j) goto lbl490;
- k3 = kk;
- lbl500: kk = np[++j];
- if(kk < 0) goto lbl500;
- if(kk != j) goto lbl490;
- np[j] = -j;
- if(j != nn) goto lbl500;
- maxf *= inc;
- /* Perform reordering following permutation cycles */
- goto lbl570;
- lbl510: j--;
- if (np[j] < 0) goto lbl510;
- jj = jc;
- lbl520: kspan = jj;
- if(jj > maxf)
- kspan = maxf;
- jj -= kspan;
- k = np[j];
- kk = (jc*k) + i + jj;
- k1 = kk + kspan;
- k2 = 0;
- lbl530: k2++;
- at[k2] = a[k1];
- bt[k2] = b[k1];
- k1 -= inc;
- if(k1 != kk) goto lbl530;
- lbl540: k1 = kk + kspan;
- k2 = k1 - (jc * (k + np[k]));
- k = -(np[k]);
- lbl550: a[k1] = a[k2];
- b[k1] = b[k2];
- k1 -= inc;
- k2 -= inc;
- if(k1 != kk) goto lbl550;
- kk = k2;
- if(k != j) goto lbl540;
- k1 = kk + kspan;
- k2 = 0;
- lbl560: k2++;
- a[k1] = at[k2];
- b[k1] = bt[k2];
- k1 -= inc;
- if(k1 != kk) goto lbl560;
- if(jj) goto lbl520;
- if(j != 1) goto lbl510;
- lbl570: j = k3 + 1;
- nt -= kspnn;
- i = nt - inc + 1;
- if(nt >= 0) goto lbl510;
- return(FINISHED);;
- }
- /*
- *-----------------------------------------------------------------------
- * subroutine: reals
- * used with 'fft' to compute fourier transform or inverse for real data
- *-----------------------------------------------------------------------
- * this is the call from C:
- * reals_(anal,banal,N2,mtwo);
- * which has been changed from CARL call
- * reals_(anal,banal,&N2,&mtwo);
- */
- int reals_(float *a, float *b, int n, int isn)
- /* a refers to an array of floats 'anal' */
- /* b refers to an array of floats 'banal' */
- /* See IEEE book for a long comment here on usage */
- { int inc,
- j,
- k,
- lim,
- mm,ml,
- nf,nk,nh;
-
- double aa,ab,
- ba,bb,
- cd,cn,
- dr,
- em,
- rad,re,
- sd,sn;
- double xx; /******* ADDED APRIL 1991 ******/
- /* adjust input array pointers (called from C) */
- a--; b--;
- inc=abs(isn);
- nf=abs(n);
- if(nf*isn==0){
- sprintf(errstr,"zero in reals parameters in FFT : %d : %d ",n,isn);
- return(DATA_ERROR);;
- }
- nk = (nf*inc) + 2;
- nh = nk/2;
- /*****************************
- rad = atan((double)1.0);
- ******************************/
- rad = 0.785398163397448278900;
- dr = -4.0/(double)(nf);
- /********************************** POW2 REMOVED APRIL 1991 *****************
- cd = 2.0 * (pow2(sin((double)0.5 * dr * rad)));
- *****************************************************************************/
- xx = sin((double)0.5 * dr * rad);
- cd = 2.0 * xx * xx;
- sd = sin(dr * rad);
- /*
- * sin,cos values are re-initialized each lim steps
- */
- lim = 32;
- mm = lim;
- ml = 0;
- sn = 0.0;
- if(isn<0){
- cn = 1.0;
- a[nk-1] = a[1];
- b[nk-1] = b[1]; }
- else {
- cn = -1.0;
- sd = -sd;
- }
- for(j=1;j<=nh;j+=inc) {
- k = nk - j;
- aa = a[j] + a[k];
- ab = a[j] - a[k];
- ba = b[j] + b[k];
- bb = b[j] - b[k];
- re = (cn*ba) + (sn*ab);
- em = (sn*ba) - (cn*ab);
- b[k] = (float)((em-bb)*0.5);
- b[j] = (float)((em+bb)*0.5);
- a[k] = (float)((aa-re)*0.5);
- a[j] = (float)((aa+re)*0.5);
- ml++;
- if(ml!=mm){
- aa = cn - ((cd*cn)+(sd*sn));
- sn = ((sd*cn) - (cd*sn)) + sn;
- cn = aa;}
- else {
- mm +=lim;
- sn = ((float)ml) * dr * rad;
- cn = cos(sn);
- if(isn>0)
- cn = -cn;
- sn = sin(sn);
- }
- }
- return(FINISHED);
- }
- /************************ SA_INITIALISE_SPECENV ************************/
- int sa_initialise_specenv(dataptr dz)
- {
- int arraycnt;
- dz->clength = dz->wanted/2;
- dz->nyquist = dz->infile->srate/2.0;
- dz->chwidth = dz->nyquist/(double)(dz->iparam[SA_CHANS] / 2);
- arraycnt = dz->clength + 1;
- if((dz->specenvfrq = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for formant frq array.\n");
- return(MEMORY_ERROR);
- }
- if((dz->specenvpch = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for formant pitch array.\n");
- return(MEMORY_ERROR);
- }
- /*RWD zero the data */
- memset(dz->specenvpch,0,arraycnt * sizeof(float));
- if((dz->specenvamp = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for formant aplitude array.\n");
- return(MEMORY_ERROR);
- }
- if((dz->specenvtop = (float *)malloc(arraycnt * sizeof(float)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY for formant frq limit array.\n");
- return(MEMORY_ERROR);
- }
- return(FINISHED);
- }
- /************************ SA_SET_SPECENV_FRQS ************************
- *
- * FREQWISE BANDS = number of channels for each specenv point
- * PICHWISE BANDS = number of points per octave
- */
- int sa_set_specenv_frqs(dataptr dz)
- {
- int exit_status;
- int arraycnt;
- double bandbot;
- double *interval;
- int m, n, k = 0, cc;
- arraycnt = dz->clength + 1;
- if((exit_status = sa_setup_octaveband_steps(&interval,dz))<0)
- return(exit_status);
- if((exit_status = sa_setup_low_octave_bands(arraycnt,dz))<0)
- return(exit_status);
- k = TOP_OF_LOW_OCTAVE_BANDS;
- cc = CHAN_ABOVE_LOW_OCTAVES;
- while(cc <= dz->clength) {
- m = 0;
- if((bandbot = dz->chwidth * (double)cc) >= dz->nyquist)
- break;
- for(n=0;n<dz->iparam[SA_FORMANT_BANDS];n++) {
- if(k >= arraycnt) {
- sprintf(errstr,"Formant array too small: sa_set_specenv_frqs()\n");
- return(PROGRAM_ERROR);
- }
- dz->specenvfrq[k] = (float)(bandbot * interval[m++]);
- dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
- dz->specenvtop[k++] = (float)(bandbot * interval[m++]);
- }
- cc *= 2; /* 8-16: 16-32: 32-64 etc as 8vas, then split into bands */
- }
- dz->specenvfrq[k] = (float)dz->nyquist;
- dz->specenvpch[k] = (float)log10(dz->nyquist);
- dz->specenvtop[k] = (float)dz->nyquist;
- dz->specenvamp[k] = (float)0.0;
- k++;
- dz->infile->specenvcnt = k;
- return(FINISHED);
- }
- /************************* SA_SETUP_OCTAVEBAND_STEPS ************************/
- int sa_setup_octaveband_steps(double **interval,dataptr dz)
- {
- double octave_step;
- int n = 1, m = 0, halfbands_per_octave = dz->iparam[SA_FORMANT_BANDS] * 2;
- if((*interval = (double *)malloc(halfbands_per_octave * sizeof(double)))==NULL) {
- sprintf(errstr,"INSUFFICIENT MEMORY establishing interval array for formants.\n");
- return(MEMORY_ERROR);
- }
- while(n < halfbands_per_octave) {
- octave_step = (double)n++/(double)halfbands_per_octave;
- (*interval)[m++] = pow(2.0,octave_step);
- }
- (*interval)[m] = 2.0;
- return(FINISHED);
- }
- /************************ SA_SETUP_LOW_OCTAVE_BANDS ***********************
- *
- * Lowest PVOC channels span larger freq steps and therefore we must
- * group them in octave bands, rather than in anything smaller.
- */
- int sa_setup_low_octave_bands(int arraycnt,dataptr dz)
- {
- int n;
- arraycnt = dz->clength + 1;
- if(arraycnt < LOW_OCTAVE_BANDS) {
- sprintf(errstr,"Insufficient array space for low_octave_bands\n");
- return(PROGRAM_ERROR);
- }
- for(n=0;n<LOW_OCTAVE_BANDS;n++) {
- switch(n) {
- case(0):
- dz->specenvfrq[0] = (float)1.0; /* frq whose log is 0 */
- dz->specenvpch[0] = (float)0.0;
- dz->specenvtop[0] = (float)dz->chwidth; /* 8VA wide bands */
- break;
- case(1):
- dz->specenvfrq[1] = (float)(dz->chwidth * 1.5); /* Centre Chs 1-2 */
- dz->specenvpch[1] = (float)log10(dz->specenvfrq[1]);
- dz->specenvtop[1] = (float)(dz->chwidth * 2.0);
- break;
- case(2):
- dz->specenvfrq[2] = (float)(dz->chwidth * 3.0); /* Centre Chs 2-4 */
- dz->specenvpch[2] = (float)log10(dz->specenvfrq[2]);
- dz->specenvtop[2] = (float)(dz->chwidth * 4.0);
- break;
- case(3):
- dz->specenvfrq[3] = (float)(dz->chwidth * 6.0); /* Centre Chs 4-8 */
- dz->specenvpch[3] = (float)log10(dz->specenvfrq[3]);
- dz->specenvtop[3] = (float)(dz->chwidth * 8.0);
- break;
- default:
- sprintf(errstr,"Insufficient low octave band setups in sa_setup_low_octave_bands()\n");
- return(PROGRAM_ERROR);
- }
- }
- return(FINISHED);
- }
- /********************** SA_EXTRACT_SPECENV *******************/
- int sa_extract_specenv(float *anal,dataptr dz)
- {
- int n, cc, vc, specenvcnt_less_one;
- int botchan, topchan;
- double botfreq, topfreq;
- double bwidth_in_chans;
- float *ampstore;
- ampstore = dz->specenvamp;
- specenvcnt_less_one = dz->infile->specenvcnt - 1;
- vc = 0;
- for(n=0;n<dz->infile->specenvcnt;n++)
- ampstore[n] = (float)0.0;
- topfreq = 0.0f;
- n = 0;
- while(n < specenvcnt_less_one) {
- botfreq = topfreq;
- botchan = (int)((botfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- botchan -= CHAN_SRCHRANGE_F;
- botchan = max(botchan,0);
- topfreq = dz->specenvtop[n];
- topchan = (int)((topfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
- topchan += CHAN_SRCHRANGE_F;
- topchan = min(topchan,dz->clength);
- for(cc = botchan,vc = botchan * 2; cc < topchan; cc++,vc += 2) {
- if(anal[FREQ] < 0.0) // rectify if ness
- anal[FREQ] = (float)-anal[FREQ];
- if(anal[FREQ] >= botfreq && anal[FREQ] < topfreq)
- ampstore[n] = (float)(ampstore[n] + anal[AMPP]);
- }
- bwidth_in_chans = (double)(topfreq - botfreq)/dz->chwidth;
- ampstore[n] = (float)(ampstore[n]/bwidth_in_chans);
- n++;
- }
- return(FINISHED);
- }
- /**************************** IS_A_HARMONIC_X *************************/
- int is_a_harmonic_x(double frq1,double fundamental)
- {
- double ratio;
- int iratio, hcnt;
- double intvl, harmonicfrq;
- harmonicfrq = fundamental;
- hcnt = 1;
- while(harmonicfrq < frq1 * SEMITONE_INTERVAL) {
- ratio = frq1/harmonicfrq;
- iratio = round(ratio);
- if(iratio != 1) {
- if(ratio > iratio)
- intvl = ratio/(double)iratio;
- else
- intvl = (double)iratio/ratio;
- if(intvl < quartertone)
- return(TRUE);
- }
- hcnt++;
- harmonicfrq = fundamental * hcnt;
- }
- return(FALSE);
- }
- /******************************** EXTRACT_ENV_FROM_SNDFILE *****************************/
-
- int extract_env_from_sndfile(dataptr dz)
- {
- int n, i;
- float *buffer = dz->sampbuf[0];
- double thismaxsamp, thisval;
- for(n = 0; n < dz->envcnt; n++) {
- if((dz->ssampsread = fgetfbufEx(buffer, dz->iparam[SA_TSTEP],dz->ifd[0],0)) < 0) {
- sprintf(errstr,"Can't read samples from soundfile: to extract envelope.\n");
- return(SYSTEM_ERROR);
- }
- thismaxsamp = 0.0;
- for(i = 0; i<dz->ssampsread; i++) {
- if((thisval = fabs(buffer[i]))>thismaxsamp)
- thismaxsamp = thisval;
- }
- dz->env[n] = (float)thismaxsamp;
- }
- // NORMALISE
- thismaxsamp = -HUGE;
- for(n = 0; n < dz->envcnt; n++)
- thismaxsamp = max(thismaxsamp,dz->env[n]);
- if(thismaxsamp <= 0.0) {
- sprintf(errstr,"No significant level found in source sound.\n");
- return DATA_ERROR;
- }
- for(n = 0; n < dz->envcnt; n++)
- dz->env[n] = (float)(dz->env[n]/thismaxsamp);
- memset((char *)buffer,0,(dz->iparam[SA_TSTEP] * 2) * sizeof(float));
- sndseekEx(dz->ifd[0],0,0);
- return(FINISHED);
- }
- /******************************************* GET_TEMPERED_PITCH ********************************/
- int get_tempered_pitch(float *averages, float *averages2, float *averages3, dataptr dz)
- {
- double maxval;
- int maxpos;
- int *pitches = dz->iparray[0];
- int jj, kk;
- if(dz->pitchcnt != 0) {
- for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
- averages3[kk] = averages[kk] + averages2[kk]; // sum average levels from last 2 groups
- maxval = -10000;
- maxpos = 0;
- // For every semitone bin // Find loudest frq
- for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2) {
- if(averages3[kk] > maxval) { // is it the loudest
- maxval = averages3[kk];
- maxpos = jj;
- }
- }
- pitches[dz->pitchcnt] = maxpos - 1; // assign pitch (MIDI bins start at midi = -1 : so bin2 is midi=1)
- }
- memcpy((char *)averages2,(char *)averages,(BINCNT *2) * sizeof(float));
- for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
- averages[kk] = 0.0;
- dz->pitchcnt++;
- return FINISHED;
- }
- /******************************************* GET_TEMPERED_HF ********************************/
- int get_tempered_hf(float *averages, float *averages2, float *averages3, dataptr dz)
- {
- double maxval;
- int maxpos;
- int jj, kk, mm;
- if(dz->pitchcnt != 0) {
- for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
- averages3[kk] = averages[kk] + averages2[kk]; // sum average levels from last 2 groups
- for(mm = 0; mm < 8;mm++) { // Get the 8 loudest peaks, in loudness order
- maxval = -10000;
- maxpos = 0;
- // For every semitone bin // Find loudest frq
- for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2) {
- if(averages3[kk] > maxval) { // is it the loudest
- maxval = averages3[kk];
- maxpos = jj;
- }
- }
- dz->iparray[mm][dz->pitchcnt] = maxpos - 1; // assign pitch (MIDI bins start at midi = -1 : so bin2 is midi=1)
- kk = (maxpos * 2) + 1;
- averages3[kk] = -10000; // set the current loudest bin to a -ve val, so it is ignored in next pass of mm loop
- }
- }
- memcpy((char *)averages2,(char *)averages,(BINCNT *2) * sizeof(float));
- for(jj = 0, kk= 1; jj < BINCNT; jj++, kk+=2)
- averages[kk] = 0.0;
- dz->pitchcnt++;
- return FINISHED;
- }
- /******************************************* SMOOTH_AND_OUTPUT_TEMPERED_PITCH ********************************/
- int smooth_and_output_tempered_pitch(dataptr dz)
- {
- int n, m, t, k;
- int *pitches = dz->iparray[0], lastpitch, thispitch, pitchrepet;
- double *pichout = dz->parray[0], transittime;
- /* Put times into array */
- for(n=1, t = 2, m = 3;n < dz->envcnt; n++,t+=2,m+=2) {
- pichout[t] = dz->param[SA_TSTEP] * n; // Time
- pichout[m] = pitches[n]; // Pitch
- }
- for(n=1,m=2;n<dz->envcnt;n++,m+=2) {
- if(dz->env[n] < dz->param[SA_GATE]) // Mark for deletion, pitches found at below gate-level
- pichout[m] = -1.0;
- if(pichout[m] >= 0.0) {
- if((int)round(pichout[m+1]) < dz->param[SA_BOTRANGE])
- pichout[m] = -1; // Mark for deletion, pitches below acceptable range
- else if((int)round(pichout[m+1]) > dz->param[SA_TOPRANGE])
- pichout[m] = -1; // Mark for deletion, pitches below acceptable range
- }
- }
- n = 1;
- m = 2;
- while(n<dz->envcnt-1) {
- if(pichout[m] < 0.0) {
- for(k = m+2; k < dz->envcnt*2; k++) // Shuffle-down overwrite
- pichout[k-2] = pichout[k];
- dz->envcnt--;
- } else {
- n++;
- m += 2;
- }
- }
- if(pichout[m] < 0.0)
- dz->envcnt--;
- for(n=1,m=2;n<dz->envcnt;n++,m+=2) {
- if(flteq(pichout[m+1],pichout[m-1])) // Mark for deletion, pitches that duplicate the previous pitch
- pichout[m] = -1;
- }
- n = 1;
- m = 2;
- while(n<dz->envcnt-1) {
- if(pichout[m] < 0.0) {
- for(k = m+2; k < dz->envcnt*2; k++) // Shuffle-down overwrite
- pichout[k-2] = pichout[k];
- dz->envcnt--;
- } else {
- n++;
- m += 2;
- }
- }
-
- if(pichout[m] < 0.0)
- dz->envcnt--;
- if(dz->envcnt == 0) {
- sprintf(errstr,"NO PITCHES FOUND\n");
- return DATA_ERROR;
- }
- pichout[0] = 0.0; // Force a value at time zero
- pichout[1] = pichout[3];
- // Reduce data (where pitch is repeated)
- lastpitch = (int)round(pichout[1]);
- pitchrepet = 0;
- for(n = 1;n< dz->envcnt;n++) {
- k = n * 2; // time-index in output array
- m = k+1; // pitch-index in output array
- thispitch = (int)round(pichout[m]);
- if(thispitch == lastpitch)
- pitchrepet++;
- else {
- if(pitchrepet) { // If a pitch repeats
- k = n; // Copy pitches down over eliminated pitches
- m = n - pitchrepet;
- k = k * 2;
- m = m * 2;
- while(k < dz->envcnt * 2)
- pichout[m++] = pichout[k++];
- dz->envcnt -= pitchrepet;
- n -= pitchrepet;
- }
- lastpitch = thispitch;
- pitchrepet = 0;
- }
- }
- for(n = 0,m=0;n< dz->envcnt;n++,m+=2) {
- fprintf(dz->fp,"%f\t%d\t1\n",pichout[m],(int)round(pichout[m+1]));
- if(n < dz->envcnt-1) {
- transittime = min(SA_TRANSIT,(pichout[m+2] - pichout[m])/2.0);
- fprintf(dz->fp,"%f\t%d\t1\n",pichout[m+2] - transittime,(int)round(pichout[m+1]));
- } else
- fprintf(dz->fp,"10000\t%d\t1\n",(int)round(pichout[m+1]));
- }
- return FINISHED;
- }
- /******************************************* SMOOTH_AND_OUTPUT_VARYING_HF ********************************/
- int smooth_and_output_varying_hf(dataptr dz)
- {
- int exit_status, reranged[8] = {0}, lastpitch[8], thispitch[8], does_repeat;
- int n, m, t, k, f, omitsum = 0, hfrepet;
- int itemp, peakcnt, omit[8];
- double transittime, temp;
- char tempstr[4000], tempstr2[4000];
- int downtranspos = 0;
- /* Eliminate harmonics of lower peaks */
- if(dz->iparam[SA_PKCNT] < 8) {
- for(n=1;n < dz->envcnt; n++) { /* Initially, arrays 0-7 run from loudest to quietest pitch */
- for(m=0,k = 7;m<4;m++,k--) { /* invert order of array pitches at time 'n', so they run from quietest to loudest */
- itemp = dz->iparray[m][n];
- dz->iparray[m][n] = dz->iparray[k][n];
- dz->iparray[k][n] = itemp;
- }
- peakcnt = 8;
- for(m=0;m<8;m++) {
- if(dz->iparray[m][n] < 0) // skip arrays that have already been eliminated from search
- continue;
- for(t=0;t<peakcnt;t++) { // Compare each peak pitch with all others
- if(t==m) // except itself
- continue;
- if(dz->iparray[t][n] < 0) // skip arrays that have already been eliminated from search
- continue;
- // If one partial is a harmonic of another, mark it for elimination
- 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) {
- dz->iparray[m][n] = -1;
- peakcnt--; // count remaining peaks
- break; // and abandon comparison with other peaks
- }
- }
- if(peakcnt <= dz->iparam[SA_PKCNT])// if only the required no of peaks remains, stop
- break;
- }
- for(m=0,k = 7;m<4;m++,k--) { /* invert order of array pitches at time 'n', so loudest is below quietest */
- itemp = dz->iparray[m][n];
- dz->iparray[m][n] = dz->iparray[k][n];
- dz->iparray[k][n] = itemp;
- }
- k = 0; // Move SA_PKCNT valid peaks to topmost arrays 0 to SA_PKCNT-1
- for(m=0;m<8;m++) {
- if(dz->iparray[m][n] >= 0) {
- if(k!=m) // Move item up arrays only if ness
- dz->iparray[k][n] = dz->iparray[m][n];
- k++;
- if(k >= dz->iparam[SA_PKCNT])
- break;
- }
- }
- }
- }
- /* Put times into arrays */
- for(n=1, t = 2, m = 3;n < dz->envcnt; n++,t+=2,m+=2) {
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- dz->parray[k][t] = dz->param[SA_TSTEP] * n; // Time
- dz->parray[k][m] = (double)dz->iparray[k][n]; // Pitch
- }
- }
- for(n=1,t=2;n<dz->envcnt;n++,t+=2) {
- if(dz->env[n] < dz->param[SA_GATE]) // Mark for deletion, pitches found where sound is below gate-level
- dz->parray[0][t] = -1.0;
- }
- n = 1;
- m = 2;
- while(n<dz->envcnt-1) {
- if(dz->parray[0][m] < 0.0) {
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- for(t = m+2; t < dz->envcnt*2; t++) // Shuffle-down overwrite
- dz->parray[k][t-2] = dz->parray[k][t];
- }
- dz->envcnt--;
- } else {
- n++;
- m += 2;
- }
- }
- if(dz->parray[0][m] < 0.0)
- dz->envcnt--;
- if(dz->envcnt == 0) {
- sprintf(errstr,"NO PITCHES FOUND\n");
- return DATA_ERROR;
- }
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- dz->parray[k][0] = 0.0; // Force a value at time zero
- dz->parray[k][1] = dz->parray[k][3];
- }
- // Force pitches, at each time 'n', into ascending order
- for(n=0,f=1;n<dz->envcnt;n++,f+=2) {
- for(k=0;k<dz->iparam[SA_PKCNT]-1;k++) {
- for(m=k+1;m<dz->iparam[SA_PKCNT];m++) {
- if(dz->parray[m][f] < dz->parray[k][f]) {
- temp = dz->parray[k][f];
- dz->parray[k][f] = dz->parray[m][f];
- dz->parray[m][f] = temp;
- }
- }
- }
- }
- // If any filter strand is everywhere out of range, mark it for elimination
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- omit[k] = 1;
- for(n=0,f=1;n<dz->envcnt;n++,f+=2) {
- if(dz->parray[k][f] >= dz->param[SA_BOTRANGE] && dz->parray[k][f] <= dz->param[SA_TOPRANGE]) {
- omit[k] = 0;
- break;
- }
- }
- }
- // Delete out-of-range threads by shuffle-down overwrite
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- if(omit[k]) {
- omitsum++;
- if(k < dz->iparam[SA_PKCNT] - 1) {
- for(m=k+1;m<dz->iparam[SA_PKCNT];m++)
- dz->parray[m-1] = dz->parray[m];
- }
- if(--(dz->iparam[SA_PKCNT]) <= 0) {
- sprintf(errstr,"ALL EXTRACTED HARMONIC FIELD COMPONENTS ARE OUT OF RANGE.\n");
- return DATA_ERROR;
- }
- }
- }
- if(omitsum) {
- if(omitsum == 1)
- fprintf(stdout,"WARNING: 1 PEAK-STRAND ENTIRELY OUT OF RANGE. REDUCED PEAK-COUNT TO %d\n",dz->iparam[SA_PKCNT]);
- else
- fprintf(stdout,"WARNING: %d PEAK-STRANDS ARE ENTIRELY OUT OF RANGE. REDUCED PEAK-COUNT TO %d\n",omitsum,dz->iparam[SA_PKCNT]);
- fflush(stdout);
- }
-
- // Data-reduce (remove repeating filters)
- for(t = 0;t < dz->iparam[SA_PKCNT];t++)
- lastpitch[t] = (int)round(dz->parray[t][1]);
- hfrepet = 0;
- for(n = 1;n< dz->envcnt;n++) {
- k = n * 2; // time-index in output arrays
- m = k+1; // pitch-index in output arrays
- does_repeat = 1;
- for(t = 0;t < dz->iparam[SA_PKCNT];t++) {
- thispitch[t] = (int)round(dz->parray[t][m]);
- if(thispitch[t] != lastpitch[t]) { // If this and lasttime pitches are NOT the same
- // if both are out of range, both are zeroed in the output, so in effect equivalent
- if((thispitch[t] < dz->param[SA_BOTRANGE] || thispitch[t] > dz->param[SA_TOPRANGE])
- && (lastpitch[t] < dz->param[SA_BOTRANGE] || lastpitch[t] > dz->param[SA_TOPRANGE]))
- continue;
- does_repeat = 0; // Otherwise, pitches not the same, so HF not repeated.
- break;
- }
- }
- if(does_repeat)
- hfrepet++;
- else {
- if(hfrepet) { // If an HF repeats
- k = n; // Copy all HF pitches down over eliminated pitches
- m = k - hfrepet;
- k = k * 2;
- m = m * 2;
- while(k < dz->envcnt * 2) {
- for(t = 0;t < dz->iparam[SA_PKCNT];t++)
- dz->parray[t][m] = dz->parray[t][k];
- k++;
- m++;
- }
- dz->envcnt -= hfrepet;
- n -= hfrepet;
- }
- for(t = 0;t < dz->iparam[SA_PKCNT];t++)
- lastpitch[t] = thispitch[t];
- hfrepet = 0;
- }
- }
- // Attempt downward octave transpos, if flagged
- if(dz->vflag[SA_DOWNOCT]) {
- downtranspos = 1;
- for(n = 0,t=1;n < dz->envcnt;n++,t+=2) {
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- if(dz->parray[0][m+1] - 12.0 < 0) {
- downtranspos = 0;
- break;
- }
- }
- if(k<dz->iparam[SA_PKCNT])
- break;
- }
- if(!downtranspos) {
- fprintf(stdout,"WARNING: OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
- fflush(stdout);
- }
- } else if(dz->vflag[SA_DOWN2OCT]) {
- downtranspos = 2;
- for(n = 0,t=1;n < dz->envcnt;n++,t+=2) {
- for(k=0;k<dz->iparam[SA_PKCNT];k++) {
- if(dz->parray[0][m+1] - 24.0 < 0) {
- downtranspos = 0;
- break;
- }
- }
- if(k<dz->iparam[SA_PKCNT])
- break;
- }
- if(!downtranspos) {
- fprintf(stdout,"WARNING: TWO OCTAVE DOWN TRANSPOSITION NOT POSSIBLE.\n");
- fflush(stdout);
- }
- }
- // Print to output, zeroing any out-of-range pitches
- for(n = 0,m=0;n < dz->envcnt;n++,m+=2) {
- reranged[0] = 0;
- if(dz->parray[0][m+1] < dz->param[SA_BOTRANGE] || dz->parray[0][m+1] > dz->param[SA_TOPRANGE]) {
- // FORCE ELEMENT TO BE IN RANGE, BUT ZERO IT
- if((exit_status = rerange_outofrange_pitch(0,n,dz))<0)
- return exit_status;
- reranged[0] = 1;
- if(downtranspos)
- dz->parray[0][m+1] -= (12.0 * downtranspos);
- sprintf(tempstr,"%f\t%d\t0",dz->parray[0][m],(int)round(dz->parray[0][m+1]));
- } else {
- if(downtranspos)
- dz->parray[0][m+1] -= 12.0;
- sprintf(tempstr,"%f\t%d\t1",dz->parray[0][m],(int)round(dz->parray[0][m+1]));
- }
- for(k=1;k<dz->iparam[SA_PKCNT];k++) {
- reranged[k] = 0;
- if(dz->parray[k][m+1] < dz->param[SA_BOTRANGE] || dz->parray[k][m+1] > dz->param[SA_TOPRANGE]) {
- if((exit_status = rerange_outofrange_pitch(k,n,dz))<0)
- return exit_status;
- reranged[k] = 1;
- if(downtranspos)
- dz->parray[k][m+1] -= 12.0;
- sprintf(tempstr2,"\t%d\t0",(int)round(dz->parray[k][m+1]));
- } else {
- if(downtranspos)
- dz->parray[k][m+1] -= 12.0;
- sprintf(tempstr2,"\t%d\t1",(int)round(dz->parray[k][m+1]));
- }
- strcat(tempstr,tempstr2);
- }
- fprintf(dz->fp,"%s\n",tempstr);
- if(n < dz->envcnt-1) {
- transittime = min(SA_TRANSIT,(dz->parray[0][m+2] - dz->parray[0][m])/2.0);
- if(reranged[0])
- sprintf(tempstr,"%f\t%d\t0",dz->parray[0][m+2] - transittime,(int)round(dz->parray[0][m+1]));
- else
- sprintf(tempstr,"%f\t%d\t1",dz->parray[0][m+2] - transittime,(int)round(dz->parray[0][m+1]));
- for(k=1;k<dz->iparam[SA_PKCNT];k++) {
- if(reranged[k])
- sprintf(tempstr2,"\t%d\t0",(int)round(dz->parray[k][m+1]));
- else
- sprintf(tempstr2,"\t%d\t1",(int)round(dz->parray[k][m+1]));
- strcat(tempstr,tempstr2);
- }
- fprintf(dz->fp,"%s\n",tempstr);
- }
- }
- // Extend end value to beyond source end
- if(reranged[0])
- sprintf(tempstr,"10000\t%d\t0",(int)round(dz->parray[0][m-1]));
- else
- sprintf(tempstr,"10000\t%d\t1",(int)round(dz->parray[0][m-1]));
- for(k=1;k<dz->iparam[SA_PKCNT];k++) {
- if(reranged[k])
- sprintf(tempstr2,"\t%d\t0",(int)round(dz->parray[k][m-1]));
- else
- sprintf(tempstr2,"\t%d\t1",(int)round(dz->parray[k][m-1]));
- strcat(tempstr,tempstr2);
- }
- fprintf(dz->fp,"%s\n",tempstr);
- return FINISHED;
- }
- /********************************************** RERANGE_OUTOFRANGE_PITCH **************************************
- *
- * If outofrange pitches remian in the filter definition they
- * (1) May cause unwanted glissi at transition points (from one pitch to another) in a filter thread
- * (2) May produce a false reading for the highest possible harmonic in the varibank interface.
- */
- int rerange_outofrange_pitch(int strandindex,int eventindex,dataptr dz)
- {
- int gotpre = 0, gotpost = 0;
- int thisevent, pitchindex;
- double prepitch = 0, postpitch = 0, newpitch;
- if(eventindex > 0) {
- thisevent = eventindex;
- while(thisevent > 0) { // Find 1st earlier pitch which is in range
- thisevent--;
- pitchindex = (thisevent * 2) + 1;
- if(dz->parray[strandindex][pitchindex] < dz->param[SA_BOTRANGE] || dz->parray[strandindex][pitchindex] > dz->param[SA_TOPRANGE])
- continue;
- else {
- gotpre = 1;
- prepitch = dz->parray[strandindex][pitchindex];
- break;
- }
- }
- }
- if(eventindex < dz->envcnt-1) {
- thisevent = eventindex; // Find first later pitch which is in range
- while(thisevent < dz->envcnt) {
- thisevent++;
- pitchindex = (thisevent * 2) + 1;
- if(dz->parray[strandindex][pitchindex] < dz->param[SA_BOTRANGE] || dz->parray[strandindex][pitchindex] > dz->param[SA_TOPRANGE])
- continue;
- else {
- gotpost = 1;
- postpitch = dz->parray[strandindex][pitchindex];
- break;
- }
- }
- }
- if(!gotpre && !gotpost) {
- sprintf(errstr,"ERROR IN OUT-OF-RANGE PITCH PROCESSING.\n");
- return PROGRAM_ERROR;
- }
- if(gotpre && gotpost)
- newpitch = (double)((int)round((prepitch + postpitch)/2.0));
- else if(!gotpre)
- newpitch = postpitch;
- else
- newpitch = prepitch;
- pitchindex = (eventindex * 2) + 1;
- dz->parray[strandindex][pitchindex] = newpitch;
- return FINISHED;
- }
- //RWD 2025 zero error checking - will already have been done!
- static int checkchans4format(int chans, const char* fname)
- {
- char *lastdot;
-
- lastdot = strrchr(fname,'.');
- if(chans > 8192){
- if((_stricmp(lastdot,".wav")==0)
- || (_stricmp(lastdot,".ana")==0))
- return 0;
- }
-
- return 1;
- }
|