specfnu.c 358 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243924492459246924792489249925092519252925392549255925692579258925992609261926292639264926592669267926892699270927192729273927492759276927792789279928092819282928392849285928692879288928992909291929292939294929592969297929892999300930193029303930493059306930793089309931093119312931393149315931693179318931993209321932293239324932593269327932893299330933193329333933493359336933793389339934093419342934393449345934693479348934993509351935293539354935593569357935893599360936193629363936493659366936793689369937093719372937393749375937693779378937993809381938293839384938593869387938893899390939193929393939493959396939793989399940094019402940394049405940694079408940994109411941294139414941594169417941894199420942194229423942494259426942794289429943094319432943394349435943694379438943994409441944294439444944594469447944894499450945194529453945494559456945794589459946094619462946394649465946694679468946994709471947294739474947594769477947894799480948194829483948494859486948794889489949094919492949394949495949694979498949995009501950295039504950595069507950895099510951195129513951495159516951795189519952095219522952395249525952695279528952995309531953295339534953595369537953895399540954195429543954495459546954795489549955095519552955395549555955695579558955995609561956295639564956595669567956895699570957195729573957495759576957795789579958095819582958395849585958695879588958995909591959295939594959595969597959895999600960196029603960496059606960796089609961096119612961396149615961696179618961996209621962296239624962596269627962896299630963196329633963496359636963796389639964096419642964396449645964696479648964996509651965296539654965596569657965896599660966196629663966496659666966796689669967096719672967396749675967696779678967996809681968296839684968596869687968896899690969196929693969496959696969796989699970097019702970397049705970697079708970997109711971297139714971597169717971897199720972197229723972497259726972797289729973097319732973397349735973697379738973997409741974297439744974597469747974897499750975197529753975497559756975797589759976097619762976397649765976697679768976997709771
  1. // SEE FILE temp.cpp for pitch-modification originals to import here!!!!
  2. //
  3. // _cdprogs\specfnu specfnu 23 alan_bellydancefbn.ana test.wav hague_trials\triadhf.txt 1 -n1 -o1 -p1 -q1 -S
  4. //
  5. // Spectral channels are dz->specenvamp && dz->specenvfrq
  6. // dz->specenvamp[0] = (float)0.0;
  7. // dz->specenvfrq[0] = (float)1.0;
  8. // frqstep = dz->halfchwidth * (double)dz->formant_bands;
  9. // Defaulting to 12 so we get a spectral channel widtth of c 260hz (and smaller window option give 86Hz bands)
  10. //
  11. //#define SEECHANGE 1
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <structures.h>
  15. #include <tkglobals.h>
  16. #include <pnames.h>
  17. #include <filetype.h>
  18. #include <processno.h>
  19. #include <modeno.h>
  20. #include <logic.h>
  21. #include <globcon.h>
  22. #include <cdpmain.h>
  23. #include <formants.h>
  24. #include <math.h>
  25. #include <mixxcon.h>
  26. #include <osbind.h>
  27. #include <standalone.h>
  28. #include <science.h>
  29. #include <speccon.h>
  30. #include <ctype.h>
  31. #include <sfsys.h>
  32. #include <string.h>
  33. #include <srates.h>
  34. #ifdef unix
  35. #define round lround
  36. #endif
  37. #define VIEWSCALE (1.0e3) // Multiplier enabling pvoc amplitudes to be easily read in any on-screen debug print
  38. #define warned is_rectified
  39. #define pktrofcnt rampbrksize
  40. #define xclude_nonh temp_sampsize
  41. #define badpks fzeroset
  42. #define suprflag unspecified_filecnt // Used by F_SUPPRESS and F_NARROW
  43. #define timedhf unspecified_filecnt // Used by F_SINUS
  44. #define phasefactor is_flat
  45. #define bincnt different_srates
  46. #define quantcnt finished
  47. #define in_tune is_sharp
  48. #define fundamental numsize
  49. #define avfrq maxnum
  50. #define timeblokcnt sampswanted
  51. #define ischange could_be_transpos
  52. #define shortwins duplicate_snds
  53. #define frq_step scalefact
  54. #define needpitch could_be_pitch
  55. #define fsil_ratio minnum
  56. #define retain_unpitched_data_for_deletion is_transpos
  57. // PROCESSING PASSES
  58. #define FPREANAL 0
  59. #define FSPECENV 1
  60. #define FPROCESS 2
  61. // ARRAY NAMES
  62. // integer array names
  63. #define PEAKPOS 0 // iparray[0]
  64. #define PCNTBIN 1 // iparray[1]
  65. #define FCNT 2 // iparray[2]
  66. #define ISHARM 3 // iparray[3]
  67. #define IARRAYCNT 4 // Number of iparrays
  68. #define F_CHTRAIN1 4
  69. #define F_CHTRAIN2 5
  70. #define F_CHTRAIN3 6
  71. #define F_CHTRAIN4 7
  72. #define F_CHTRAIN5 8
  73. #define F_CHTRAIN6 9
  74. #define F_CHTRAIN7 10
  75. #define F_CHTRAIN8 11
  76. #define F_CHTRAIN9 12
  77. #define IBIGARRAYCNT 13 // Number of iparrays
  78. // double array names
  79. #define PBINPCH 1 // parray[1] pitch extraction
  80. #define PBINTOP 2 // parray[2]
  81. #define PBINAMP 3 // parray[3]
  82. #define PREPICH 4 // parray[4] sorting input pitch data
  83. #define QUANTPITCH 5 // parray[5] pitch quantisation
  84. #define FILTPICH 5 // parray[5] filter design
  85. #define FILTAMP 6 // parray[6]
  86. #define LOCALPCH 7 // parray[7]
  87. #define LOCALAMP 8 // parray[8]
  88. #define FMULT 9 // parray[9] concatenation of moving formants
  89. #define FPITCHES 9 // parray[9] All pitches actually used by varibank filter
  90. #define FSPEC3 10 // parray[10]
  91. #define PRE_P_ARRAYCNT 11 // Total number of arrays, excluding arrays needed for pitch extraction
  92. #define P_PRETOTAMP 11 // parray[11] loudness envelope extraction (and pitch-smoothing)
  93. #define RUNNINGAVRG 12 // parray[12] pitch smoothing
  94. #define RUNAVGDURS 13 // parray[13]
  95. #define F_PINTMAP 14 // parray[14] stores interval-map for pitch-inversion over HFs
  96. #define TOT_DBLARRAYCNT 15 // Total number of double arrays
  97. // float array names
  98. // spec peaks-and-trofs data
  99. #define PKTROF 0 // fptr[0] peaks-and-trofs
  100. #define PKDIFF 1 // fptr[1] peak-trof differences
  101. // filter-line storage for varibank filter data in F_MAKEFILT
  102. #define FILTLINE 2 // fptr[2]
  103. #define LASTFLINE 3 // fptr[3]
  104. // peaks-and-trofs data for moved formants
  105. #define FAMP1 2 // fptr[2]
  106. #define FAMP2 3 // fptr[3]
  107. #define FAMP3 4 // fptr[4]
  108. #define FAMP4 5 // fptr[5]
  109. #define FFRQ1 6 // fptr[6]
  110. #define FFRQ2 7 // fptr[7]
  111. #define FFRQ3 8 // fptr[8]
  112. #define FFRQ4 9 // fptr[9]
  113. #define FPCH1 10 // fptr[10]
  114. #define FPCH2 11 // fptr[11]
  115. #define FPCH3 12 // fptr[12]
  116. #define FPCH4 13 // fptr[13]
  117. // arrays for storing formant pitch data
  118. #define FOR_FRQ1 2 // Alternative names
  119. #define FOR_FRQ2 3 // for same arrays
  120. #define FOR_FRQ3 4 // when used by
  121. #define FOR_FRQ4 5 // F_SINUS
  122. #define QOR_FRQ1 6
  123. #define QOR_FRQ2 7
  124. #define QOR_FRQ3 8
  125. #define QOR_FRQ4 9
  126. #define P_SINUS_ARRAYS 8// Number of arrays used in storing and manipulating formant pitch-streams:
  127. // from F_AMP1 to QOR_FRQ4
  128. #define PKSARRAYCNT 14 // Number of float arrays for dealing with peak/trof detection & moving formants
  129. // harmonics detection
  130. #define HMNICBOUNDS 14 // fptr[14]
  131. // contour extraction
  132. #define CONTOURFRQ 15 // fptr[15]
  133. #define CONTOURPCH 16 // fptr[16]
  134. #define CONTOURAMP 17 // fptr[17]
  135. #define CONTOURTOP 18 // fptr[18]
  136. #define CONTOURAMP2 19 // fptr[19]
  137. #define TOTAL_FLARRAYCNT 20 // Total number of float array
  138. // int arrays
  139. #define FTIMES 0 // lparray[0] Counting time-breaks in building filter : F_MAKEFILT
  140. #define AVSTT 1 // lparray[1] Counting during continuity_smoothing of pitch data
  141. #define TOTAL_LPARRAYCNT 2 // Total number of int arrays
  142. // ESTABLISHING FORMANT BANDS AMD CONTOUR ENVELOPE SIZE
  143. #define SPECFNU_SHORT_FBANDS 4 //
  144. #define SPECFNU_FBANDS 12 // Choose value to give best peak separation (but not too many peaks) This is no of HAlF channel-widths
  145. #define SPECFNU_LONG_FBANDS 72
  146. #define CLENGTH_DEFAULT 512 // Default number of analysis points (AP): AP determines window-width,
  147. // NO OF PEAKS + TROFS TO STORE
  148. #define PKBLOK 9 // 5 trofs and 4 peaks = 9 points
  149. // DETECTION OF FUNDAMENTAL
  150. #define TWO_OVER_THREE 0.6666
  151. // DETECTION OF HARMONICS
  152. #define WITHIN_RANGE 1 // Semitone range for a partial to be considered a fundamental of the peak harmonic (or vice versa)
  153. // PITCH PROCESSING
  154. #define FMAXIMI (8) // No of (max) peaks to use to check for harmonicity
  155. #define FCHANSCAN (8) // No of channels to scan looking for equivalent pitches at possible peak
  156. #define FPEAK_LIMIT (.05)
  157. #define MAXIMUM_PARTIAL (64) // Maximum partial to search for
  158. #define ALMOST_TWO (1.5) // Approximating 8ve leaps, when looking for 8va leap anomalies
  159. #define EIGHT_OVER_SEVEN (1.142857143) // Intervals within which pitch is "close" to existing frequency
  160. #define SEVEN_OVER_EIGHT (0.875)
  161. #define GOOD_MATCH (5) // No of peaks that must be harmonics for window to register as pitched
  162. #define FBLIPLEN (2) // Number of adjacent windows that must be pitched for pitch not to be spurious is MORE THAN FBLIPLEN
  163. #define FSILENCE_RATIO (42) // Any window falling SILENCE_RATIO dBs below maximum window-level assumed to be "silence"
  164. #define FPICH_HILM (dz->nyquist/FMAXIMI)//High limit of pitch to search for (as we need FMAXIMI peaks to search for pitch)
  165. #define FMIN_SMOOTH_SET (3) // Minimum number of adjacent smooth pitches to imply true pitch present
  166. #define FMAX_GLISRATE (16.0) // Assumptions: pitch can't move faster than 16 octaves per sec: FMAX_GLISRATE
  167. // Possible movement from window-to-window = FMAX_GLISRATE * dz->frametime
  168. #define VOICEHI (1500.0) // F# above C 2 8vas abive middle C
  169. #define MVOICEHI (500) // B above middle C
  170. #define VOICELO (48.0) // G below C 2 8vas below middle C
  171. // PITCH INTERPOLATION
  172. #define FMID_PITCH (0)
  173. #define FFIRST_PITCH (1)
  174. #define FEND_PITCH (2)
  175. #define FNO_PITCH (3)
  176. #define TOO_SHORT_PICH (0.1) // Segment of pitchedness within line must be longer than this, to register
  177. #define TOO_SHORT_UNPICH (0.05) // Segment of unpitchedness within line must be longer than this, to register
  178. // SPECTRUM PITCH-TRANSPOSITION
  179. #define FSPEC_MINFRQ (9.0)
  180. // F_SEE
  181. #define SPECFNU_MAXLEVEL (0.95) // Max level for normalisation
  182. #define SPECFNU_BLOKCNT 7 // Number of samples of equal value forming a block for display in output of F_SEE
  183. // F_NARROW
  184. #define F4_ZEROED 8 // Last formant(4) being zeroed is flagged by 4th bit in suprflag (1000) = 8
  185. // F_MAKEFILE
  186. #define MIDIOCTSPAN 11 // 0-127 = 10 octaves (120) + 7semitones. so 11 octaves spans the range
  187. #define MINWINDOWS 60 // Min no of windows over which a filter can be defined
  188. #define FILTER_STAGGER 0.05 // Time between filter settings, when filters change
  189. #define FILTER_BAD_LEAP (SEMITONES_PER_OCTAVE * 1.5)
  190. // F_MOVE(2)
  191. #define F_LOFRQ_LIMIT (1.0)
  192. #define F_HIFRQ_LIMIT (dz->nyquist/2.0)
  193. // F_SYLABTROF
  194. // COLORING ARPEGGIATION
  195. #define ARPEG_RANGE 7.0 // Total number of partials being arpeggiated is 8 (i.e 0 to 7)
  196. #define ARPEG_WIN_WIDTH 4.0 // Number of partials under highlighting window
  197. #define ARPEG_WIN_HALFWIDTH (ARPEG_WIN_WIDTH/2.0) // Halfwifth highlighting window
  198. // SLOPE OF TAILOFF OF EXTRA PARTIALS ADDED AT SPECTRUM TOP
  199. #define TAILOFF_SLOPE 4.0
  200. #define INTERVAL_MAPPING (29) /* FILE OR VAL */ /* special_data : Map interval-->interval for spec pinvert */
  201. #define PSEUDOCTMIN (4) // Size range, in semitones, of any pseudo_octave used in tuning, or quantiosation spec
  202. #define PSEUDOCTMAX (48)
  203. #define MAXSCALECNT (100) // Max number of divisions of octave, in tuning data
  204. #define VERY_SMOOTH (0.3) // Very smooth pitchline
  205. #define STABLE_DUR (0.2) // Min duration of (quantised) pitch, which is NOT an ornament
  206. #define ORNAMENT_DUR (0.1) // Min duration of (quantised) pitch, which could be an ornament
  207. #define PCHANGE_DUR (0.05) // Time to shift pitch from one pitch to another
  208. #define PRAND_TRANGE (2.0) // Time-slot where rand-val of pitch-variation stays fixed, ranges from a minimum TO (min + 2*min)
  209. #define PRAND_TSTEP (0.05)
  210. #define PRAND_ORN_TSTEP (0.015)
  211. #define MINPITCHMIDI (1.662783) // MIDI val corresponding to MINPITCH
  212. // formant frequencies and amplitudes for 1st 3 formants : might be useful : NOT USED as at MAY 15: 2016
  213. #if 0
  214. static double heed[6] = {300,2600,2800,1.0,0.85,0.85};
  215. static double hid[6] = {360,2100,2300,1.0,1.0, 1.0 };
  216. static double educAtedScot[6] = {500,2250,2450,1.0,0.92,0.25};
  217. static double laid[6] = {465,2250,2450,1.0,0.92,0.25};
  218. static double head[6] = {570,1970,2450,1.0,1.0, 0.75};
  219. static double had[6] = {750,1550,2450,1.0,1.0, 0.85};
  220. static double hard[6] = {680,1100,2450,1.0,1.0, 0.92};
  221. static double hod[6] = {600,900, 2450,1.0,1.0, 0.5 };
  222. static double horde[6] = {450,860, 2300,1.0,1.0, 0.82};
  223. static double cokeNorthern[6] = {410,810, 2300,1.0,1.0, 0.82};
  224. static double mudNorthern[6] = {380,850, 2100,1.0,1.0, 0.6 };
  225. static double youscots[6] = {380,850, 2800,1.0,0.85,0.85};
  226. static double couldscots[6] = {380,1000,2450,1.0,0.92,0.25};
  227. static double mood[6] = {300,850, 2100,1.0,1.0, 0.6 };
  228. static double hubSouthern[6] = {720,1240,2300,1.0,0.85,0.3 };
  229. static double herd[6] = {580,1380,2450,1.0,1.0, 0.5 };
  230. static double nnn[6] = {580,1380,2625,1.0,0.0, 0.1 };
  231. static double mmmm[6] = {580,850, 2100,1.0,0.0, 0.0 };
  232. static double rrrflat[6] = {880,2100,2450,1.0,0.2, 0.0 };
  233. static double ththth[6] = {400,1000,2450,1.0,0.3, 0.2 };
  234. #endif
  235. char errstr[2400];
  236. int anal_infiles = 1;
  237. int sloom = 0;
  238. int sloombatch = 0;
  239. const char* cdp_version = "8.0.0";
  240. /* CDP LIBRARY FUNCTIONS TRANSFERRED HERE */
  241. static int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist);
  242. static int set_vflgs(aplptr ap,char *optflags,int optcnt,char *optlist,
  243. char *varflags,int vflagcnt, int vparamcnt,char *varlist);
  244. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  245. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  246. static int mark_parameter_types(dataptr dz,aplptr ap);
  247. static int establish_application(dataptr dz);
  248. static int application_init(dataptr dz);
  249. static int initialise_vflags(dataptr dz);
  250. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  251. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  252. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  253. static int assign_file_data_storage(int infilecnt,dataptr dz);
  254. /* CDP LIB FUNCTION MODIFIED TO AVOID CALLING setup_particular_application() */
  255. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  256. /* SIMPLIFICATION OF LIB FUNC TO APPLY TO JUST THIS FUNCTION */
  257. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  258. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz);
  259. static int setup_the_application(dataptr dz);
  260. static int setup_the_param_ranges_and_defaults(dataptr dz);
  261. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  262. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  263. static int get_the_mode_no(char *str, dataptr dz);
  264. static int check_specfnu_param_validity_and_consistency(dataptr dz);
  265. static int new_inner_loop(int windows_in_buf,double *fmax,int passno,int limit,int *inner_lpcnt,double *phase,int *times_index,
  266. double *target,int *previouspk,int contourcnt,int arp_param,int *up,double minpitch,double maxpitch,dataptr dz);
  267. static int set_the_specenv_frqs(int arraycnt,dataptr dz);
  268. /* BYPASS LIBRARY GLOBAL FUNCTION TO GO DIRECTLY TO SPECIFIC APPLIC FUNCTIONS */
  269. static void force_extension(int type,char *filename);
  270. static int outer_specfnu_loop(int contourcnt,dataptr dz);
  271. static int setup_formant_arrays(int *contourcnt,dataptr dz);
  272. static int formants_narrow(int inner_lpcnt,dataptr dz);
  273. static int formants_squeeze(int inner_lpcnt,dataptr dz);
  274. static int formants_invert(int inner_lpcnt,double *phase,int contourcnt,dataptr dz);
  275. static int formants_rotate(int inner_lpcnt,double *phase,dataptr dz);
  276. static int formants_see(dataptr dz);
  277. static int formants_seepks(dataptr dz);
  278. static int formants_negate(int contourcnt,dataptr dz);
  279. static int formants_suppress(int inner_lpcnt,dataptr dz);
  280. static int formants_makefilt(int inner_lpcnt,int *times_index,dataptr dz);
  281. static int formants_move(int inner_lpcnt,dataptr dz);
  282. static int get_the_formant_sample_points(dataptr dz);
  283. static int specfnu_preprocess(dataptr dz);
  284. static int initialise_peakstore(dataptr dz);
  285. static int get_peaks_and_trofs(int inner_lpcnt,int limit,int *previouspk,dataptr dz);
  286. static int usage4(int mode);
  287. static int get_fmax(double *fmax,dataptr dz);
  288. static int handle_the_makefilt_special_data(char *str,dataptr dz);
  289. static int handle_the_pquantise_special_data(char *str,dataptr dz);
  290. static int sort_pitches(dataptr dz);
  291. static int build_filter(int times_index,dataptr dz);
  292. static int find_fundamental(float thisfrq,double target,int peakcc,float *newfrq,dataptr dz);
  293. static int equivalent_pitches(double frq1, double frq2, dataptr dz);
  294. static int move_formant(int fno,double frqoffset,int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp,float hitorfamp,int *truecnt,dataptr dz);
  295. static int concatenate_moved_formants(dataptr dz);
  296. static int edgefade_formant(float *thisfrq,float *thisamp,float *thispch,int hi,
  297. int *nuchanlen, int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp, float hitrofamp,float frqlimit,dataptr dz);
  298. static int getspecenv3amp(double frq,double *amp,float *thispch,float *thisamp,int speccnt,dataptr dz);
  299. static int fwindow_size(dataptr dz);
  300. // PITCH RELATED PROCESSING
  301. static int locate_channel_of_fundamental(int inner_lpcnt,float *fundfrq, int *newcc,dataptr dz);
  302. static int continuity_smoothing(dataptr dz);
  303. // FIND PITCH
  304. static int initialise_pitchwork(int is_launched,dataptr dz);
  305. static int establish_arrays_for_pitchwork(dataptr dz);
  306. static int specpitch(int inner_lpcnt,double *target,dataptr dz);
  307. static int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz);
  308. static int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz);
  309. static int insert_in_ring(int vc, chvptr here, dataptr dz);
  310. static int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz);
  311. static int found_pitch(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,double *thepitch,dataptr dz);
  312. static int found_pitch_1(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz);
  313. static int found_pitch_2(chvptr *partials,dataptr dz);
  314. static int smooth_spurious_octave_leaps(int pitchno,float minamp,dataptr dz);
  315. static int equivalent_pitches(double frq1, double frq2, dataptr dz);
  316. static int is_peak_at(double frq,int window_offset,float minamp,dataptr dz);
  317. static int enough_partials_are_harmonics(chvptr *partials,double thepitch,dataptr dz);
  318. static int is_equivalent_pitch(double frq1,double frq2,dataptr dz);
  319. static int is_above_equivalent_pitch(double frq1,double frq2,dataptr dz);
  320. static int do_smooth(int n, double *slopechange,dataptr dz);
  321. static int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz);
  322. static int locate_channel_of_pitch(int inner_lpcnt,float thepitch, int *newcc,dataptr dz);
  323. // MASSAGE PITCH DATA
  324. static int tidy_up_pitch_data(dataptr dz);
  325. static int anti_noise_smoothing(int wlength,float *pitches,float frametime);
  326. static int is_smooth_from_both_sides(int n,double max_pglide,float *pitches);
  327. static int is_initialpitch_smooth(char *smooth,double max_pglide,float *pitches);
  328. static int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,float *pitches);
  329. static int is_smooth_from_before(int n,char *smooth,double max_pglide,float *pitches);
  330. static int is_smooth_from_after(int n,char *smooth,double max_pglide,float *pitches);
  331. static int test_glitch_sets(char *smooth,double max_pglide,int wlength,float *pitches);
  332. static void remove_unsmooth_pitches(char *smooth,int wlength,float *pitches);
  333. static int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,float *pitches);
  334. static int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,
  335. double max_pglide,int wlength,float *pitches);
  336. static int eliminate_blips_in_pitch_data(dataptr dz);
  337. static int mark_zeros_in_pitchdata(dataptr dz);
  338. static int pitch_found(dataptr dz);
  339. static int averages_smooth(int bracketed,int bracket,int runavcnt,dataptr dz);
  340. // INTERPOLATE PITCH DATA
  341. static int interpolate_pitch(dataptr dz);
  342. static int do_interpolating(int *pitchno,int skip_silence,dataptr dz);
  343. static double hz_to_pitchheight(double frqq);
  344. static double pitchheight_to_hz(double pitch_height);
  345. // OTHER PITCH-RELATED FUNCTIONS
  346. static int exclude_non_harmonics(dataptr dz);
  347. static int shufflup_harmonics_bounds(int *top_hno,float the_fundamental,int boundscnt,dataptr dz);
  348. static int channel_holds_harmonic(float the_fundamental,float frq,int cc,int *top_hno,dataptr dz);
  349. static int initialise_contourenv(int *contourcnt,int contourbands,dataptr dz);
  350. static int extract_contour(int contourcnt,dataptr dz);
  351. static int getcontouramp(double *thisamp,int contourcnt,double thisfrq,dataptr dz);
  352. static int suppress_harmonics(dataptr dz);
  353. static int getcontouramp2(double *thisamp,int contourcnt,double thisfrq,dataptr dz);
  354. static int remember_contouramp(int contourcnt,dataptr dz);
  355. static int trof_detect(dataptr dz);
  356. static void zero_spectrum_top(int cc,dataptr dz);
  357. static int is_coloring(dataptr dz);
  358. static int formants_recolor(int inner_lpcnt,double *phase,int *up,int arp_param,double minpitch,double maxpitch,int contourcnt,dataptr dz);
  359. static int arpeggiate(double *arpegamp,float frq,double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int is_split,dataptr dz);
  360. static int find_and_change_partials(float the_fundamental,float newfrq,int *isharm,double frqshift,double frqtrans,double randomisation,
  361. double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int do_arpegg,int is_split,dataptr dz);
  362. static int do_top_of_spectrum_fill(int cc,float endamp,float the_fundamental,double frqtrans,double frqshift,int *tail,dataptr dz);
  363. static int getmeanpitch(double *meanpitch,double *minpitch,double *maxpitch,dataptr dz);
  364. static int interval_mapping(double *thisint,double thismidi,dataptr dz);
  365. static int read_interval_mapping(char *str,dataptr dz);
  366. static int get_and_count_data_from_textfile(char *filename,double **brktable,dataptr dz);
  367. static int exag_pitchline(float *newfrq,float thisfrq,double minpich,double maxpich,dataptr dz);
  368. static int pitch_invert(float *newfrq,float the_fundamental,dataptr dz);
  369. static int pitch_quantise_all(dataptr dz);
  370. static double pitch_quantise(double thismidi,double *pstt, double *pend,dataptr dz);
  371. static int pitch_smooth(dataptr dz);
  372. static int pitch_randomise_all(dataptr dz);
  373. static int get_rand_interval(double *thisintv,dataptr dz);
  374. static int randomise_pitchblok(int start_win,int min_wcnt,int *newwcnt,dataptr dz);
  375. static int quantise_randomise_pitchblok(int n,int wcnt,double *pstt,double *pend,dataptr dz);
  376. static int formants_smooth_and_quantise_all(dataptr dz);
  377. static int formants_sinus(int inner_lpcnt,dataptr dz);
  378. static int store_formant_frq_data(int inner_lpcnt,dataptr dz);
  379. static int pitchline_smooth(float *pichline,int min_wcnt,int ismidi,dataptr dz);
  380. static int smooth_note_to_note_transitions(float *pichline,dataptr dz);
  381. static int sort_pitches_for_tvary_hf(int entrycnt,int linecnt,dataptr dz);
  382. static int octaviate_and_store_timed_hf_data(dataptr dz);
  383. static void strip_end_space(char *p);
  384. /**************************************** MAIN *********************************************/
  385. int main(int argc,char *argv[])
  386. {
  387. int exit_status, n;
  388. dataptr dz = NULL;
  389. char **cmdline;
  390. int cmdlinecnt, k;
  391. aplptr ap;
  392. int is_launched = FALSE;
  393. int contourcnt = 0;
  394. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  395. fprintf(stdout,"%s\n",cdp_version);
  396. fflush(stdout);
  397. return 0;
  398. }
  399. /* CHECK FOR SOUNDLOOM */
  400. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  401. sloom = 0;
  402. sloombatch = 1;
  403. }
  404. if(sflinit("cdp")){
  405. sfperror("cdp: initialisation\n");
  406. return(FAILED);
  407. }
  408. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  409. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  410. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  411. return(FAILED);
  412. }
  413. if(!sloom) {
  414. if(argc == 1) {
  415. usage1();
  416. return(FAILED);
  417. } else if(argc == 2) {
  418. usage2(argv[1]);
  419. return(FAILED);
  420. } else if(argc == 3) {
  421. usage3(argv[1],argv[2]);
  422. return(FAILED);
  423. }
  424. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  425. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  426. return(FAILED);
  427. }
  428. cmdline = argv;
  429. cmdlinecnt = argc;
  430. if((get_the_process_no(argv[0],dz))<0)
  431. return(FAILED);
  432. cmdline++;
  433. cmdlinecnt--;
  434. dz->maxmode = 23;
  435. if(cmdlinecnt <= 0) {
  436. sprintf(errstr,"Too few commandline parameters.\n");
  437. return(FAILED);
  438. }
  439. if((get_the_mode_no(cmdline[0],dz))<0) {
  440. if(!sloom)
  441. fprintf(stderr,"%s",errstr);
  442. return(FAILED);
  443. }
  444. cmdline++;
  445. cmdlinecnt--;
  446. exit_status = CONTINUE;
  447. switch(dz->mode) {
  448. case(F_NEGATE): // fall thro
  449. case(F_SEE): // fall thro
  450. case(F_SYLABTROF): // fall thro
  451. case(F_SEEPKS): if(cmdlinecnt < 2) exit_status = FAILED; break;
  452. case(F_NARROW): // fall thro
  453. case(F_ROTATE): // fall thro
  454. case(F_SUPPRESS): // fall thro
  455. case(F_ARPEG): // fall thro
  456. case(F_OCTSHIFT): // fall thro
  457. case(F_TRANS): // fall thro
  458. case(F_FRQSHIFT): // fall thro
  459. case(F_RESPACE): // fall thro
  460. case(F_PINVERT): // fall thro
  461. case(F_PQUANT): // fall thro
  462. case(F_RAND): // fall thro
  463. case(F_INVERT): if(cmdlinecnt < 3) exit_status = FAILED; break;
  464. case(F_PEXAGG): // fall thro
  465. case(F_SINUS): // fall thro
  466. case(F_MAKEFILT): // fall thro
  467. case(F_SQUEEZE):if(cmdlinecnt < 4) exit_status = FAILED; break;
  468. case(F_PCHRAND):if(cmdlinecnt < 5) exit_status = FAILED; break;
  469. case(F_MOVE2): // fall thro
  470. case(F_MOVE): if(cmdlinecnt < 6) exit_status = FAILED; break;
  471. default:
  472. fprintf(stderr,"Unknown mode (%d) at 2nd usage check.\n",dz->mode+1);
  473. return PROGRAM_ERROR;
  474. }
  475. if(exit_status == FAILED) {
  476. usage4(dz->mode);
  477. return FAILED;
  478. }
  479. if((exit_status = setup_the_application(dz))<0) {
  480. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  481. return(FAILED);
  482. }
  483. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  484. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  485. return(FAILED);
  486. }
  487. } else {
  488. //parse_TK_data() =
  489. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  490. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  491. return(exit_status);
  492. }
  493. }
  494. ap = dz->application;
  495. // parse_infile_and_hone_type() =
  496. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  497. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  498. return(FAILED);
  499. }
  500. // setup_param_ranges_and_defaults() =
  501. if((exit_status = setup_the_param_ranges_and_defaults(dz))<0) {
  502. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  503. return(FAILED);
  504. }
  505. // open_first_infile CDP LIB
  506. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  507. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  508. return(FAILED);
  509. }
  510. cmdlinecnt--;
  511. cmdline++;
  512. // handle_outfile() =
  513. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,is_launched,dz))<0) {
  514. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  515. return(FAILED);
  516. }
  517. if(!sloom) {
  518. exit_status = CONTINUE;
  519. switch(dz->mode) {
  520. case(F_SEE): // fall thro
  521. case(F_SYLABTROF): // fall thro
  522. case(F_SEEPKS): break;
  523. case(F_NARROW): // fall thro
  524. case(F_ROTATE): // fall thro
  525. case(F_SUPPRESS): // fall thro
  526. case(F_ARPEG): // fall thro
  527. case(F_OCTSHIFT): // fall thro
  528. case(F_TRANS): // fall thro
  529. case(F_FRQSHIFT): // fall thro
  530. case(F_RESPACE): // fall thro
  531. case(F_PINVERT): // fall thro
  532. case(F_PQUANT): // fall thro
  533. case(F_RAND): // fall thro
  534. case(F_INVERT): if(cmdlinecnt < 1) exit_status = FAILED; break;
  535. case(F_PEXAGG): // fall thro
  536. case(F_SINUS): // fall thro
  537. case(F_MAKEFILT): // fall thro
  538. case(F_SQUEEZE): if(cmdlinecnt < 2) exit_status = FAILED; break;
  539. case(F_PCHRAND): if(cmdlinecnt < 3) exit_status = FAILED; break;
  540. case(F_MOVE2): // fall thro
  541. case(F_MOVE): if(cmdlinecnt < 4) exit_status = FAILED; break;
  542. case(F_NEGATE): break;
  543. default:
  544. fprintf(stderr,"Unknown mode (%d) at 3rd usage check.\n",dz->mode+1);
  545. return PROGRAM_ERROR;
  546. }
  547. if(exit_status == FAILED) {
  548. usage4(dz->mode);
  549. return FAILED;
  550. }
  551. }
  552. dz->retain_unpitched_data_for_deletion = 0;
  553. if(dz->mode == F_SINUS) {
  554. if((dz->iparray = (int **)malloc(IBIGARRAYCNT * sizeof(int*)))==NULL) {
  555. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY for stores of formant tracking data.\n");
  556. fflush(stdout);
  557. return(FAILED);
  558. }
  559. for(n=0;n<IBIGARRAYCNT;n++)
  560. dz->iparray[n] = NULL;
  561. } else {
  562. if((dz->iparray = (int **)malloc(IARRAYCNT * sizeof(int*)))==NULL) {
  563. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY for store of locations of peaks and troughs(1).\n");
  564. fflush(stdout);
  565. return(FAILED);
  566. }
  567. }
  568. if((dz->parray = (double **)malloc(TOT_DBLARRAYCNT * sizeof(double *)))==NULL) {
  569. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store Filter Data.\n");
  570. fflush(stdout);
  571. return(FAILED);
  572. }
  573. for(n=0;n<TOT_DBLARRAYCNT;n++)
  574. dz->parray[n] = NULL;
  575. if((dz->fptr = (float **)malloc(TOTAL_FLARRAYCNT * sizeof(float *)))==NULL) {
  576. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store Intermediate formant data.\n");
  577. fflush(stdout);
  578. return(FAILED);
  579. }
  580. for(n=0;n < TOTAL_FLARRAYCNT;n++)
  581. dz->fptr[n] = NULL;
  582. if((dz->lparray = (int **)malloc(TOTAL_LPARRAYCNT * sizeof(int *)))==NULL) {
  583. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store Filter Times Data.(1)\n");
  584. fflush(stdout);
  585. return(FAILED);
  586. }
  587. // handle_formant_quiksearch() redundant
  588. // handle_special_data ....
  589. switch(dz->mode) {
  590. case(F_MAKEFILT):
  591. if((exit_status = handle_the_makefilt_special_data(cmdline[0],dz))<0) {
  592. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  593. return(FAILED);
  594. }
  595. cmdlinecnt--;
  596. cmdline++;
  597. break;
  598. case(F_PINVERT):
  599. if((exit_status = read_interval_mapping(cmdline[0],dz))<0) {
  600. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  601. return(FAILED);
  602. }
  603. cmdlinecnt--;
  604. cmdline++;
  605. break;
  606. case(F_PCHRAND): // fall thro
  607. case(F_PQUANT):
  608. if((exit_status = handle_the_pquantise_special_data(cmdline[0],dz))<0) {
  609. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  610. return(FAILED);
  611. }
  612. cmdlinecnt--;
  613. cmdline++;
  614. break;
  615. case(F_SINUS):
  616. if((exit_status = handle_the_pquantise_special_data(cmdline[0],dz))<0) {
  617. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  618. return(FAILED);
  619. }
  620. cmdlinecnt--;
  621. cmdline++;
  622. break;
  623. }
  624. if(!sloom && dz->mode == F_NARROW) {
  625. for(k = 0;k < cmdlinecnt;k++) {
  626. if(!strncmp(cmdline[k],"-s",2)) {
  627. if(strlen(cmdline[k]) > 2) {
  628. fprintf(stderr,"'-s' flag is for \"Use short windows\". Use '-o' for \"Suppress listed formants\".\n");
  629. return FAILED;
  630. }
  631. }
  632. }
  633. }
  634. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  635. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  636. return(FAILED);
  637. }
  638. //check_param_validity_and_consistency ....
  639. dz->fundamental = 0;
  640. dz->needpitch = 0;
  641. if((exit_status = check_specfnu_param_validity_and_consistency(dz))<0) {
  642. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  643. return(FAILED);
  644. }
  645. if((exit_status = exclude_non_harmonics(dz)) < 0) {
  646. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  647. return(FAILED);
  648. }
  649. if((exit_status = suppress_harmonics(dz)) < 0) {
  650. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  651. return(FAILED);
  652. }
  653. if(dz->xclude_nonh) { // To exclude non-harmonic components
  654. dz->fundamental = 1; // Need ot know the fundamental
  655. dz->needpitch = 1; // So need to do pitch-processing
  656. }
  657. if(dz->needpitch || dz->mode == F_SYLABTROF || dz->mode == F_SINUS) {
  658. if((exit_status = initialise_pitchwork(is_launched,dz))<0) {
  659. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  660. return(FAILED);
  661. }
  662. }
  663. // handle_formants .. Replace FORMANT BANDS param of previous formant-progs, with fixed val SPECFNU_FBANDS that works: val = length of specenv-window in 1/2chans.
  664. if((exit_status = fwindow_size(dz))<0) {
  665. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  666. return(FAILED);
  667. }
  668. if(dz->shortwins)
  669. dz->formant_bands = SPECFNU_SHORT_FBANDS;
  670. else
  671. dz->formant_bands = SPECFNU_FBANDS;
  672. if(dz->mode == F_INVERT || dz->mode == F_NEGATE)
  673. contourcnt = 1;
  674. is_launched = TRUE;
  675. //allocate_large_buffers() ...
  676. dz->extra_bufcnt = 1;
  677. dz->bptrcnt = 4;
  678. if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0) {
  679. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  680. return(FAILED);
  681. }
  682. if((exit_status = setup_formant_arrays(&contourcnt,dz))<0) {
  683. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  684. return(FAILED);
  685. }
  686. if((dz->windowbuf[0] = (float *)malloc(dz->wanted * sizeof(float)))==NULL) {
  687. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonics markers.\n");
  688. return(MEMORY_ERROR);
  689. }
  690. if((exit_status = allocate_single_buffer(dz)) < 0) {
  691. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  692. return(FAILED);
  693. }
  694. dz->flbufptr[2] = dz->bigfbuf + dz->buflen; // End of buffer marker
  695. //param_preprocess ....
  696. if((exit_status = specfnu_preprocess(dz)) < 0) {
  697. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  698. return(FAILED);
  699. }
  700. //spec_process_file =
  701. if((exit_status = outer_specfnu_loop(contourcnt,dz)) < 0) {
  702. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  703. return(FAILED);
  704. }
  705. if((exit_status = complete_output(dz))<0) { // CDP LIB
  706. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  707. return(FAILED);
  708. }
  709. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  710. free(dz);
  711. return(SUCCEEDED);
  712. }
  713. /**********************************************
  714. REPLACED CDP LIB FUNCTIONS
  715. **********************************************/
  716. /****************************** SET_PARAM_DATA *********************************/
  717. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  718. {
  719. ap->special_data = (char)special_data;
  720. ap->param_cnt = (char)paramcnt;
  721. ap->max_param_cnt = (char)maxparamcnt;
  722. if(ap->max_param_cnt>0) {
  723. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  724. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  725. return(MEMORY_ERROR);
  726. }
  727. strcpy(ap->param_list,paramlist);
  728. }
  729. return(FINISHED);
  730. }
  731. /****************************** SET_VFLGS *********************************/
  732. int set_vflgs
  733. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  734. {
  735. ap->option_cnt = (char) optcnt; /*RWD added cast */
  736. if(optcnt) {
  737. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  738. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  739. return(MEMORY_ERROR);
  740. }
  741. strcpy(ap->option_list,optlist);
  742. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  743. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  744. return(MEMORY_ERROR);
  745. }
  746. strcpy(ap->option_flags,optflags);
  747. }
  748. ap->vflag_cnt = (char) vflagcnt;
  749. ap->variant_param_cnt = (char) vparamcnt;
  750. if(vflagcnt) {
  751. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  752. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  753. return(MEMORY_ERROR);
  754. }
  755. strcpy(ap->variant_list,varlist);
  756. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  757. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  758. return(MEMORY_ERROR);
  759. }
  760. strcpy(ap->variant_flags,varflags);
  761. }
  762. return(FINISHED);
  763. }
  764. /***************************** APPLICATION_INIT **************************/
  765. int application_init(dataptr dz)
  766. {
  767. int exit_status;
  768. int storage_cnt;
  769. int tipc, brkcnt;
  770. aplptr ap = dz->application;
  771. if(ap->vflag_cnt>0)
  772. initialise_vflags(dz);
  773. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  774. ap->total_input_param_cnt = (char)tipc;
  775. if(tipc>0) {
  776. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  777. return(exit_status);
  778. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  779. return(exit_status);
  780. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  781. return(exit_status);
  782. }
  783. brkcnt = tipc;
  784. if(brkcnt>0) {
  785. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  786. return(exit_status);
  787. }
  788. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  789. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  790. return(exit_status);
  791. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  792. return(exit_status);
  793. }
  794. if((exit_status = mark_parameter_types(dz,ap))<0)
  795. return(exit_status);
  796. // establish_infile_constants() replaced by
  797. dz->infilecnt = ONE_NONSND_FILE;
  798. //establish_bufptrs_and_extra_buffers():
  799. return(FINISHED);
  800. }
  801. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  802. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  803. {
  804. int n;
  805. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  806. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  807. return(MEMORY_ERROR);
  808. }
  809. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  810. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  811. return(MEMORY_ERROR);
  812. }
  813. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  814. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  815. return(MEMORY_ERROR);
  816. }
  817. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  818. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  819. return(MEMORY_ERROR);
  820. }
  821. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  822. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  823. return(MEMORY_ERROR);
  824. }
  825. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  826. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  827. return(MEMORY_ERROR);
  828. }
  829. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  830. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  831. return(MEMORY_ERROR);
  832. }
  833. for(n=0;n<brkcnt;n++) {
  834. dz->brk[n] = NULL;
  835. dz->brkptr[n] = NULL;
  836. dz->brkinit[n] = 0;
  837. dz->brksize[n] = 0;
  838. }
  839. return(FINISHED);
  840. }
  841. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  842. /* RWD mallo changed to calloc; helps debug verison run as release! */
  843. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  844. {
  845. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  846. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  847. return(MEMORY_ERROR);
  848. }
  849. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  850. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  851. return(MEMORY_ERROR);
  852. }
  853. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  854. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  855. return(MEMORY_ERROR);
  856. }
  857. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  858. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  859. return(MEMORY_ERROR);
  860. }
  861. return(FINISHED);
  862. }
  863. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  864. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  865. {
  866. int n;
  867. for(n=0;n<storage_cnt;n++) {
  868. dz->is_int[n] = (char)0;
  869. dz->no_brk[n] = (char)0;
  870. }
  871. return(FINISHED);
  872. }
  873. /***************************** MARK_PARAMETER_TYPES **************************/
  874. int mark_parameter_types(dataptr dz,aplptr ap)
  875. {
  876. int n, m; /* PARAMS */
  877. for(n=0;n<ap->max_param_cnt;n++) {
  878. switch(ap->param_list[n]) {
  879. case('0'): break; /* dz->is_active[n] = 0 is default */
  880. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  881. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  882. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  883. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  884. default:
  885. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  886. return(PROGRAM_ERROR);
  887. }
  888. } /* OPTIONS */
  889. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  890. switch(ap->option_list[n]) {
  891. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  892. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  893. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  894. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  895. default:
  896. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  897. return(PROGRAM_ERROR);
  898. }
  899. } /* VARIANTS */
  900. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  901. switch(ap->variant_list[n]) {
  902. case('0'): break;
  903. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  904. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  905. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  906. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  907. default:
  908. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  909. return(PROGRAM_ERROR);
  910. }
  911. } /* INTERNAL */
  912. for(n=0,
  913. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  914. switch(ap->internal_param_list[n]) {
  915. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  916. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  917. case('d'): dz->no_brk[m] = (char)1; break;
  918. default:
  919. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  920. return(PROGRAM_ERROR);
  921. }
  922. }
  923. return(FINISHED);
  924. }
  925. /***************************** HANDLE_THE_OUTFILE **************************/
  926. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz)
  927. {
  928. int exit_status, len, orig_chans = 1;
  929. char *filename = NULL;
  930. len = strlen((*cmdline)[0]);
  931. if((filename = (char *)malloc(len + 8))==NULL) {
  932. sprintf(errstr,"handle_the_outfile()\n");
  933. return(MEMORY_ERROR);
  934. }
  935. strcpy(filename,(*cmdline)[0]);
  936. if(dz->mode == F_SEEPKS || dz->mode == F_SYLABTROF || dz->mode == F_MAKEFILT)
  937. force_extension(1,filename);
  938. else
  939. force_extension(0,filename);
  940. strcpy(dz->outfilename,filename);
  941. if(dz->mode == F_SEE) {
  942. orig_chans = dz->infile->channels;
  943. dz->infile->channels = 1;
  944. }
  945. if((exit_status = create_sized_outfile(filename,dz))<0)
  946. return(exit_status);
  947. if(dz->mode == F_SEE)
  948. dz->infile->channels = orig_chans;
  949. (*cmdline)++;
  950. (*cmdlinecnt)--;
  951. return(FINISHED);
  952. }
  953. /***************************** ESTABLISH_APPLICATION **************************/
  954. int establish_application(dataptr dz)
  955. {
  956. aplptr ap;
  957. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  958. sprintf(errstr,"establish_application()\n");
  959. return(MEMORY_ERROR);
  960. }
  961. ap = dz->application;
  962. memset((char *)ap,0,sizeof(struct applic));
  963. return(FINISHED);
  964. }
  965. /************************* INITIALISE_VFLAGS *************************/
  966. int initialise_vflags(dataptr dz)
  967. {
  968. int n;
  969. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  970. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  971. return(MEMORY_ERROR);
  972. }
  973. for(n=0;n<dz->application->vflag_cnt;n++)
  974. dz->vflag[n] = FALSE;
  975. return FINISHED;
  976. }
  977. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  978. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  979. {
  980. int n;
  981. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  982. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  983. return(MEMORY_ERROR);
  984. }
  985. for(n=0;n<tipc;n++)
  986. ap->default_val[n] = 0.0;
  987. return(FINISHED);
  988. }
  989. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  990. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  991. {
  992. int n;
  993. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  994. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  995. return(MEMORY_ERROR);
  996. }
  997. for(n=0;n<tipc;n++)
  998. dz->is_active[n] = (char)0;
  999. return(FINISHED);
  1000. }
  1001. /************************* SETUP_THE_APPLICATION *******************/
  1002. int setup_the_application(dataptr dz)
  1003. {
  1004. int exit_status;
  1005. aplptr ap;
  1006. if((exit_status = establish_application(dz))<0) // GLOBAL
  1007. return(FAILED);
  1008. ap = dz->application;
  1009. // SEE parstruct FOR EXPLANATION of next 2 functions
  1010. switch(dz->mode) {
  1011. // resynth modes
  1012. case(F_NARROW): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1013. case(F_SQUEEZE): exit_status = set_param_data(ap,0 ,2,2,"Di"); break;
  1014. case(F_INVERT): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1015. case(F_ROTATE): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1016. case(F_NEGATE): exit_status = set_param_data(ap,0 ,2,0,"00"); break;
  1017. case(F_SUPPRESS):exit_status = set_param_data(ap,0 ,2,1,"i0"); break;
  1018. // text-out mode
  1019. case(F_MAKEFILT):exit_status = set_param_data(ap,FFILT,2,1,"i0"); break;
  1020. // resynth modes
  1021. case(F_MOVE): exit_status = set_param_data(ap,0 ,4,4,"DDDD"); break;
  1022. case(F_MOVE2): exit_status = set_param_data(ap,0 ,4,4,"DDDD"); break;
  1023. case(F_ARPEG): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1024. case(F_OCTSHIFT):exit_status = set_param_data(ap,0 ,2,1,"I0"); break;
  1025. case(F_TRANS): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1026. case(F_FRQSHIFT):exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1027. case(F_RESPACE): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1028. case(F_PINVERT): exit_status = set_param_data(ap,INTERVAL_MAPPING,2,1,"D0"); break;
  1029. case(F_PEXAGG): exit_status = set_param_data(ap,0 ,2,2,"DD"); break;
  1030. case(F_PQUANT): exit_status = set_param_data(ap,HFIELD,2,0,"00"); break;
  1031. case(F_PCHRAND): exit_status = set_param_data(ap,HFIELD_OR_ZERO,2,2,"DD"); break;
  1032. case(F_RAND): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1033. // psuedosnd-out mode
  1034. case(F_SEE): break;
  1035. // text-out modes
  1036. case(F_SEEPKS): break;
  1037. case(F_SYLABTROF): break;
  1038. // resynth modes
  1039. case(F_SINUS): exit_status = set_param_data(ap,HFIELD_OR_ZERO,2,1,"D0"); break;
  1040. default:
  1041. fprintf(stderr,"Unknown mode at setup_the_application()\n");
  1042. return PROGRAM_ERROR;
  1043. }
  1044. if(exit_status < 0)
  1045. return(FAILED);
  1046. switch(dz->mode) {
  1047. // resynth modes
  1048. case(F_NARROW): exit_status = set_vflgs(ap,"go",2,"di","tfsxkr",6,0,"000000");break;
  1049. case(F_SQUEEZE): exit_status = set_vflgs(ap,"g", 1,"d", "tfsxkr",6,0,"000000");break;
  1050. case(F_INVERT): exit_status = set_vflgs(ap,"g", 1,"d", "sxkr", 4,0,"0000"); break;
  1051. case(F_ROTATE): exit_status = set_vflgs(ap,"g", 1,"d", "sxkr", 4,0,"0000"); break;
  1052. case(F_NEGATE): exit_status = set_vflgs(ap,"g", 1,"d", "f", 1,0,"0"); break;
  1053. case(F_SUPPRESS): exit_status = set_vflgs(ap,"g", 1,"d", "sx", 2,0,"00"); break;
  1054. // text-out modes
  1055. case(F_MAKEFILT): exit_status = set_vflgs(ap,"b", 1,"d", "kifs", 4,0,"0000"); break;
  1056. // resynth modes
  1057. case(F_MOVE): exit_status = set_vflgs(ap,"g", 1,"d", "tsxkr", 5,0,"00000"); break;
  1058. case(F_MOVE2): exit_status = set_vflgs(ap,"g", 1,"d", "tsnxkr",6,0,"000000");break;
  1059. case(F_ARPEG): exit_status = set_vflgs(ap,"g", 1,"d", "sxrdc", 5,0,"00000"); break;
  1060. case(F_OCTSHIFT): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1061. case(F_TRANS): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1062. case(F_FRQSHIFT): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1063. case(F_RESPACE): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1064. case(F_PINVERT): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdc", 5,0,"00000"); break;
  1065. case(F_PEXAGG): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdcTFMAB",10,0,"000000000"); break;
  1066. case(F_PQUANT): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdcon", 7,0,"0000000"); break;
  1067. case(F_PCHRAND): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdconk", 8,0,"00000000"); break;
  1068. case(F_RAND): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdc", 5,0,"00000"); break;
  1069. // psuedosnd-out mode
  1070. case(F_SEE): exit_status = set_vflgs(ap,"", 0,"" , "s", 1,0,"0"); break;
  1071. // text-out modes
  1072. case(F_SEEPKS): exit_status = set_vflgs(ap,"", 0,"" , "s", 1,0,"0"); break;
  1073. case(F_SYLABTROF):exit_status = set_vflgs(ap,"sp",2,"dd","PB", 2,0,"00"); break;
  1074. // resynth modes
  1075. case(F_SINUS): exit_status = set_vflgs(ap,"abcdeqpon",9,"dDDDDDDDD","sfrS",4,0,"0000");break;
  1076. }
  1077. if(exit_status < 0)
  1078. return(FAILED);
  1079. dz->has_otherfile = FALSE;
  1080. dz->input_data_type = ANALFILE_ONLY;
  1081. switch(dz->mode) {
  1082. case(F_SEE):
  1083. dz->process_type = PSEUDOSNDFILE;
  1084. dz->outfiletype = SNDFILE_OUT;
  1085. break;
  1086. case(F_SEEPKS): // fall thro
  1087. case(F_SYLABTROF): // fall thro
  1088. case(F_MAKEFILT):
  1089. dz->process_type = TO_TEXTFILE;
  1090. dz->outfiletype = TEXTFILE_OUT;
  1091. break;
  1092. default:
  1093. dz->process_type = BIG_ANALFILE; // Add zero windowS at end, to avoid click
  1094. dz->outfiletype = ANALFILE_OUT;
  1095. }
  1096. return application_init(dz); //GLOBAL
  1097. }
  1098. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  1099. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  1100. {
  1101. int exit_status;
  1102. infileptr infile_info;
  1103. if(!sloom) {
  1104. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  1105. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  1106. return(MEMORY_ERROR);
  1107. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  1108. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  1109. return(PROGRAM_ERROR);
  1110. } else if(infile_info->filetype != ANALFILE) {
  1111. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  1112. return(DATA_ERROR);
  1113. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  1114. sprintf(errstr,"Failed to copy file parsing information\n");
  1115. return(PROGRAM_ERROR);
  1116. }
  1117. free(infile_info);
  1118. }
  1119. dz->clength = dz->wanted / 2;
  1120. dz->chwidth = dz->nyquist/(double)(dz->clength-1);
  1121. dz->halfchwidth = dz->chwidth/2.0;
  1122. return(FINISHED);
  1123. }
  1124. /************************* SETUP_THE_PARAM_RANGES_AND_DEFAULTS *******************/
  1125. int setup_the_param_ranges_and_defaults(dataptr dz)
  1126. {
  1127. int exit_status;
  1128. aplptr ap = dz->application;
  1129. // set_param_ranges()
  1130. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  1131. // NB total_input_param_cnt is > 0 !!!s
  1132. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  1133. return(FAILED);
  1134. // get_param_ranges()
  1135. switch(dz->mode) {
  1136. case(F_NARROW):
  1137. ap->lo[NARROWING] = 1.0;
  1138. ap->hi[NARROWING] = 1000.0;
  1139. ap->default_val[NARROWING] = 2.0;
  1140. ap->lo[NARSUPRES] = 0;
  1141. ap->hi[NARSUPRES] = 234;
  1142. ap->default_val[NARSUPRES] = 0;
  1143. ap->lo[FGAIN] = 0.01;
  1144. ap->hi[FGAIN] = 10.0;
  1145. ap->default_val[FGAIN] = 1.0;
  1146. break;
  1147. case(F_SQUEEZE):
  1148. ap->lo[SQZFACT] = 1.0;
  1149. ap->hi[SQZFACT] = 10.0;
  1150. ap->default_val[SQZFACT] = 2.0;
  1151. ap->lo[SQZAT] = 1;
  1152. ap->hi[SQZAT] = 4;
  1153. ap->default_val[SQZAT] = 1;
  1154. ap->lo[FGAIN] = 0.01;
  1155. ap->hi[FGAIN] = 10.0;
  1156. ap->default_val[FGAIN] = 1.0;
  1157. break;
  1158. case(F_INVERT):
  1159. ap->lo[FVIB] = 0.0;
  1160. ap->hi[FVIB] = 300.0;
  1161. ap->default_val[FVIB] = 0.0;
  1162. ap->lo[FGAIN] = 0.01;
  1163. ap->hi[FGAIN] = 10.0;
  1164. ap->default_val[FGAIN] = 1.0;
  1165. break;
  1166. case(F_ROTATE):
  1167. ap->lo[RSPEED] = -300.0;
  1168. ap->hi[RSPEED] = 300.0;
  1169. ap->default_val[RSPEED] = 1.0;
  1170. ap->lo[FGAIN] = 0.01;
  1171. ap->hi[FGAIN] = 10.0;
  1172. ap->default_val[FGAIN] = 1.0;
  1173. break;
  1174. case(F_NEGATE):
  1175. ap->lo[FGAIN] = 0.01;
  1176. ap->hi[FGAIN] = 10.0;
  1177. ap->default_val[FGAIN] = 1.0;
  1178. break;
  1179. case(F_SUPPRESS):
  1180. ap->lo[SUPRF] = 1;
  1181. ap->hi[SUPRF] = 1234;
  1182. ap->default_val[SUPRF] = 1;
  1183. ap->lo[FGAIN] = 0.01;
  1184. ap->hi[FGAIN] = 10.0;
  1185. ap->default_val[FGAIN] = 1.0;
  1186. break;
  1187. case(F_MAKEFILT):
  1188. ap->lo[FPKCNT] = 1;
  1189. ap->hi[FPKCNT] = MAXFILTVALS;
  1190. ap->default_val[FPKCNT] = 1;
  1191. ap->lo[FBELOW] = 0;
  1192. ap->hi[FBELOW] = 127;
  1193. ap->default_val[FBELOW] = 0;
  1194. break;
  1195. case(F_MOVE):
  1196. ap->lo[FMOVE1] = -8000;
  1197. ap->hi[FMOVE1] = 8000.0;
  1198. ap->default_val[FMOVE1] = 0.0;
  1199. ap->lo[FMOVE2] = -8000;
  1200. ap->hi[FMOVE2] = 8000.0;
  1201. ap->default_val[FMOVE2] = 0.0;
  1202. ap->lo[FMOVE3] = -8000;
  1203. ap->hi[FMOVE3] = 8000.0;
  1204. ap->default_val[FMOVE3] = 0.0;
  1205. ap->lo[FMOVE4] = -8000;
  1206. ap->hi[FMOVE4] = 8000.0;
  1207. ap->default_val[FMOVE4] = 0.0;
  1208. ap->lo[FMVGAIN] = 0.01;
  1209. ap->hi[FMVGAIN] = 10.0;
  1210. ap->default_val[FMVGAIN] = 1.0;
  1211. break;
  1212. case(F_MOVE2):
  1213. ap->lo[FMOVE1] = 10;
  1214. ap->hi[FMOVE1] = 8000.0;
  1215. ap->default_val[FMOVE1] = 200;
  1216. ap->lo[FMOVE2] = 10;
  1217. ap->hi[FMOVE2] = 8000.0;
  1218. ap->default_val[FMOVE2] = 1200;
  1219. ap->lo[FMOVE3] = 10;
  1220. ap->hi[FMOVE3] = 8000.0;
  1221. ap->default_val[FMOVE3] = 2000;
  1222. ap->lo[FMOVE4] = 10;
  1223. ap->hi[FMOVE4] = 8000.0;
  1224. ap->default_val[FMOVE4] = 3200;
  1225. ap->lo[FMVGAIN] = 0.01;
  1226. ap->hi[FMVGAIN] = 10.0;
  1227. ap->default_val[FMVGAIN] = 1.0;
  1228. break;
  1229. case(F_SYLABTROF):
  1230. ap->lo[FMINSYL] = .05;
  1231. ap->hi[FMINSYL] = .5;
  1232. ap->default_val[FMINSYL] = MIN_SYLLAB_DUR; // 0.08
  1233. ap->lo[FMINPKG] = 0.01;
  1234. ap->hi[FMINPKG] = 0.2;
  1235. ap->default_val[FMINPKG] = MIN_PEAKTROF_GAP; // 0.08
  1236. break;
  1237. case(F_ARPEG):
  1238. ap->lo[FARPRATE] = -50.0;
  1239. ap->hi[FARPRATE] = 50.0;
  1240. ap->default_val[FARPRATE] = 1.0;
  1241. ap->lo[FGAIN] = 0.01;
  1242. ap->hi[FGAIN] = 10.0;
  1243. ap->default_val[FGAIN] = 1.0;
  1244. break;
  1245. case(F_OCTSHIFT):
  1246. ap->lo[COLINT] = -4.0;
  1247. ap->hi[COLINT] = 4.0;
  1248. ap->default_val[COLINT] = 1.0;
  1249. ap->lo[FGAIN] = 0.01;
  1250. ap->hi[FGAIN] = 10.0;
  1251. ap->default_val[FGAIN] = 1.0;
  1252. ap->lo[COL_LO] = 0.0;
  1253. ap->hi[COL_LO] = 10000.0;
  1254. ap->default_val[COL_LO] = 0.0;
  1255. ap->lo[COL_HI] = 50.0;
  1256. ap->hi[COL_HI] = 10000.0;
  1257. ap->default_val[COL_HI] = 0.0;
  1258. ap->lo[COLRATE] = -50.0;
  1259. ap->hi[COLRATE] = 50.0;
  1260. ap->default_val[COLRATE] = 0.0;
  1261. break;
  1262. case(F_TRANS):
  1263. ap->lo[COLFLT] = -48.0;
  1264. ap->hi[COLFLT] = 48.0;
  1265. ap->default_val[COLFLT] = 1.0;
  1266. ap->lo[FGAIN] = 0.01;
  1267. ap->hi[FGAIN] = 10.0;
  1268. ap->default_val[FGAIN] = 1.0;
  1269. ap->lo[COL_LO] = 0.0;
  1270. ap->hi[COL_LO] = 10000.0;
  1271. ap->default_val[COL_LO] = 0.0;
  1272. ap->lo[COL_HI] = 50.0;
  1273. ap->hi[COL_HI] = 10000.0;
  1274. ap->default_val[COL_HI] = 0.0;
  1275. ap->lo[COLRATE] = -50.0;
  1276. ap->hi[COLRATE] = 50.0;
  1277. ap->default_val[COLRATE] = 0.0;
  1278. break;
  1279. case(F_FRQSHIFT):
  1280. ap->lo[COLFLT] = -1000.0;
  1281. ap->hi[COLFLT] = 1000.0;
  1282. ap->default_val[COLFLT] = 100.0;
  1283. ap->lo[FGAIN] = 0.01;
  1284. ap->hi[FGAIN] = 10.0;
  1285. ap->default_val[FGAIN] = 1.0;
  1286. ap->lo[COL_LO] = 0.0;
  1287. ap->hi[COL_LO] = 10000.0;
  1288. ap->default_val[COL_LO] = 0.0;
  1289. ap->lo[COL_HI] = 50.0;
  1290. ap->hi[COL_HI] = 10000.0;
  1291. ap->default_val[COL_HI] = 0.0;
  1292. ap->lo[COLRATE] = -50.0;
  1293. ap->hi[COLRATE] = 50.0;
  1294. ap->default_val[COLRATE] = 0.0;
  1295. break;
  1296. case(F_RESPACE):
  1297. ap->lo[COLFLT] = 1.0;
  1298. ap->hi[COLFLT] = 1000.0;
  1299. ap->default_val[COLFLT] = 10.0;
  1300. ap->lo[FGAIN] = 0.01;
  1301. ap->hi[FGAIN] = 10.0;
  1302. ap->default_val[FGAIN] = 1.0;
  1303. ap->lo[COL_LO] = 0.0;
  1304. ap->hi[COL_LO] = 10000.0;
  1305. ap->default_val[COL_LO] = 0.0;
  1306. ap->lo[COL_HI] = 50.0;
  1307. ap->hi[COL_HI] = 10000.0;
  1308. ap->default_val[COL_HI] = 0.0;
  1309. ap->lo[COLRATE] = -50.0;
  1310. ap->hi[COLRATE] = 50.0;
  1311. ap->default_val[COLRATE] = .0;
  1312. break;
  1313. case(F_PINVERT):
  1314. ap->lo[COLFLT] = 0.0;
  1315. ap->hi[COLFLT] = 127;
  1316. ap->default_val[COLFLT] = 60;
  1317. ap->lo[FGAIN] = 0.01;
  1318. ap->hi[FGAIN] = 10.0;
  1319. ap->default_val[FGAIN] = 1.0;
  1320. ap->lo[COL_LO] = 0.0;
  1321. ap->hi[COL_LO] = 10000.0;
  1322. ap->default_val[COL_LO] = 0.0;
  1323. ap->lo[COL_HI] = 50.0;
  1324. ap->hi[COL_HI] = 10000.0;
  1325. ap->default_val[COL_HI] = 0.0;
  1326. ap->lo[COLRATE] = -50.0;
  1327. ap->hi[COLRATE] = 50.0;
  1328. ap->default_val[COLRATE] = 0.0;
  1329. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1330. ap->hi[COLLOPCH] = MIDIMAX;
  1331. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1332. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1333. ap->hi[COLHIPCH] = MIDIMAX;
  1334. ap->default_val[COLHIPCH] = MIDIMAX;
  1335. break;
  1336. case(F_PEXAGG):
  1337. ap->lo[COLFLT] = 0.0;
  1338. ap->hi[COLFLT] = MIDIMAX;
  1339. ap->default_val[COLFLT] = 60;
  1340. ap->lo[EXAGRANG] = 0.0;
  1341. ap->hi[EXAGRANG] = PEX_MAX_RANG;
  1342. ap->default_val[EXAGRANG] = 1.0;
  1343. ap->lo[FGAIN] = 0.01;
  1344. ap->hi[FGAIN] = 10.0;
  1345. ap->default_val[FGAIN] = 1.0;
  1346. ap->lo[COL_LO] = 0.0;
  1347. ap->hi[COL_LO] = 10000.0;
  1348. ap->default_val[COL_LO] = 0.0;
  1349. ap->lo[COL_HI] = 50.0;
  1350. ap->hi[COL_HI] = 10000.0;
  1351. ap->default_val[COL_HI] = 0.0;
  1352. ap->lo[COLRATE] = -50.0;
  1353. ap->hi[COLRATE] = 50.0;
  1354. ap->default_val[COLRATE] = 0.0;
  1355. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1356. ap->hi[COLLOPCH] = MIDIMAX;
  1357. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1358. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1359. ap->hi[COLHIPCH] = MIDIMAX;
  1360. ap->default_val[COLHIPCH] = MIDIMAX;
  1361. break;
  1362. case(F_PQUANT):
  1363. ap->lo[FGAIN] = 0.01;
  1364. ap->hi[FGAIN] = 10.0;
  1365. ap->default_val[FGAIN] = 1.0;
  1366. ap->lo[COL_LO] = 0.0;
  1367. ap->hi[COL_LO] = 10000.0;
  1368. ap->default_val[COL_LO] = 0.0;
  1369. ap->lo[COL_HI] = 50.0;
  1370. ap->hi[COL_HI] = 10000.0;
  1371. ap->default_val[COL_HI] = 0.0;
  1372. ap->lo[COLRATE] = -50.0;
  1373. ap->hi[COLRATE] = 50.0;
  1374. ap->default_val[COLRATE] = 0.0;
  1375. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1376. ap->hi[COLLOPCH] = MIDIMAX;
  1377. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1378. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1379. ap->hi[COLHIPCH] = MIDIMAX;
  1380. ap->default_val[COLHIPCH] = MIDIMAX;
  1381. break;
  1382. case(F_PCHRAND):
  1383. ap->lo[FPRMAXINT] = 0.0;
  1384. ap->hi[FPRMAXINT] = RANDPITCHMAX;
  1385. ap->default_val[FPRMAXINT] = 2.0;
  1386. ap->lo[FSLEW] = 0.1;
  1387. ap->hi[FSLEW] = 10.0;
  1388. ap->default_val[FSLEW] = 1.0;
  1389. ap->lo[FGAIN] = 0.01;
  1390. ap->hi[FGAIN] = 10.0;
  1391. ap->default_val[FGAIN] = 1.0;
  1392. ap->lo[COL_LO] = 0.0;
  1393. ap->hi[COL_LO] = 10000.0;
  1394. ap->default_val[COL_LO] = 0.0;
  1395. ap->lo[COL_HI] = 50.0;
  1396. ap->hi[COL_HI] = 10000.0;
  1397. ap->default_val[COL_HI] = 0.0;
  1398. ap->lo[COLRATE] = -50.0;
  1399. ap->hi[COLRATE] = 50.0;
  1400. ap->default_val[COLRATE] = 0.0;
  1401. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1402. ap->hi[COLLOPCH] = MIDIMAX;
  1403. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1404. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1405. ap->hi[COLHIPCH] = MIDIMAX;
  1406. ap->default_val[COLHIPCH] = MIDIMAX;
  1407. break;
  1408. case(F_RAND):
  1409. ap->lo[COLFLT] = 0.0;
  1410. ap->hi[COLFLT] = 1.0;
  1411. ap->default_val[COLFLT] = 0.1;
  1412. ap->lo[FGAIN] = 0.01;
  1413. ap->hi[FGAIN] = 10.0;
  1414. ap->default_val[FGAIN] = 1.0;
  1415. ap->lo[COL_LO] = 0.0;
  1416. ap->hi[COL_LO] = 10000.0;
  1417. ap->default_val[COL_LO] = 0.0;
  1418. ap->lo[COL_HI] = 50.0;
  1419. ap->hi[COL_HI] = 10000.0;
  1420. ap->default_val[COL_HI] = 0.0;
  1421. ap->lo[COLRATE] = -50.0;
  1422. ap->hi[COLRATE] = 50.0;
  1423. ap->default_val[COLRATE] = 0.0;
  1424. break;
  1425. case(F_SINUS):
  1426. ap->lo[F_SINING] = 0.0;
  1427. ap->hi[F_SINING] = 1.0;
  1428. ap->default_val[F_SINING] = 1.0;
  1429. ap->lo[FGAIN] = 0.01;
  1430. ap->hi[FGAIN] = 10.0;
  1431. ap->default_val[FGAIN] = 1.0;
  1432. ap->lo[F_AMP1] = 0.0;
  1433. ap->hi[F_AMP1] = 10.0;
  1434. ap->default_val[F_AMP1] = 1.0;
  1435. ap->lo[F_AMP2] = 0.0;
  1436. ap->hi[F_AMP2] = 10.0;
  1437. ap->default_val[F_AMP2] = 1.0;
  1438. ap->lo[F_AMP3] = 0.0;
  1439. ap->hi[F_AMP3] = 10.0;
  1440. ap->default_val[F_AMP3] = 1.0;
  1441. ap->lo[F_AMP4] = 0.0;
  1442. ap->hi[F_AMP4] = 10.0;
  1443. ap->default_val[F_AMP4] = 1.0;
  1444. ap->lo[F_QDEP1] = 0.0;
  1445. ap->hi[F_QDEP1] = 1.0;
  1446. ap->default_val[F_QDEP1] = 0.0;
  1447. ap->lo[F_QDEP2] = 0.0;
  1448. ap->hi[F_QDEP2] = 1.0;
  1449. ap->default_val[F_QDEP2] = 0.0;
  1450. ap->lo[F_QDEP3] = 0.0;
  1451. ap->hi[F_QDEP3] = 1.0;
  1452. ap->default_val[F_QDEP3] = 0.0;
  1453. ap->lo[F_QDEP4] = 0.0;
  1454. ap->hi[F_QDEP4] = 1.0;
  1455. ap->default_val[F_QDEP4] = 0.0;
  1456. break;
  1457. }
  1458. dz->maxmode = 23;
  1459. if(!sloom)
  1460. put_default_vals_in_all_params(dz);
  1461. return(FINISHED);
  1462. }
  1463. /********************************* PARSE_SLOOM_DATA *********************************/
  1464. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  1465. {
  1466. int exit_status;
  1467. int cnt = 1, infilecnt;
  1468. int filesize, insams, inbrksize;
  1469. double dummy;
  1470. int true_cnt = 0;
  1471. aplptr ap;
  1472. while(cnt<=PRE_CMDLINE_DATACNT) {
  1473. if(cnt > argc) {
  1474. sprintf(errstr,"Insufficient data sent from TK\n");
  1475. return(DATA_ERROR);
  1476. }
  1477. switch(cnt) {
  1478. case(1):
  1479. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  1480. sprintf(errstr,"Cannot read process no. sent from TK\n");
  1481. return(DATA_ERROR);
  1482. }
  1483. break;
  1484. case(2):
  1485. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  1486. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  1487. return(DATA_ERROR);
  1488. }
  1489. if(dz->mode > 0)
  1490. dz->mode--;
  1491. //setup_particular_application() =
  1492. if((exit_status = setup_the_application(dz))<0)
  1493. return(exit_status);
  1494. ap = dz->application;
  1495. break;
  1496. case(3):
  1497. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  1498. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  1499. return(DATA_ERROR);
  1500. }
  1501. if(infilecnt < 1) {
  1502. true_cnt = cnt + 1;
  1503. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  1504. }
  1505. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  1506. return(exit_status);
  1507. break;
  1508. case(INPUT_FILETYPE+4):
  1509. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  1510. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  1511. return(DATA_ERROR);
  1512. }
  1513. break;
  1514. case(INPUT_FILESIZE+4):
  1515. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  1516. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  1517. return(DATA_ERROR);
  1518. }
  1519. dz->insams[0] = filesize;
  1520. break;
  1521. case(INPUT_INSAMS+4):
  1522. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  1523. sprintf(errstr,"Cannot read insams sent from TK\n");
  1524. return(DATA_ERROR);
  1525. }
  1526. dz->insams[0] = insams;
  1527. break;
  1528. case(INPUT_SRATE+4):
  1529. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  1530. sprintf(errstr,"Cannot read srate sent from TK\n");
  1531. return(DATA_ERROR);
  1532. }
  1533. break;
  1534. case(INPUT_CHANNELS+4):
  1535. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  1536. sprintf(errstr,"Cannot read channels sent from TK\n");
  1537. return(DATA_ERROR);
  1538. }
  1539. break;
  1540. case(INPUT_STYPE+4):
  1541. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  1542. sprintf(errstr,"Cannot read stype sent from TK\n");
  1543. return(DATA_ERROR);
  1544. }
  1545. break;
  1546. case(INPUT_ORIGSTYPE+4):
  1547. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  1548. sprintf(errstr,"Cannot read origstype sent from TK\n");
  1549. return(DATA_ERROR);
  1550. }
  1551. break;
  1552. case(INPUT_ORIGRATE+4):
  1553. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  1554. sprintf(errstr,"Cannot read origrate sent from TK\n");
  1555. return(DATA_ERROR);
  1556. }
  1557. break;
  1558. case(INPUT_MLEN+4):
  1559. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  1560. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  1561. return(DATA_ERROR);
  1562. }
  1563. break;
  1564. case(INPUT_DFAC+4):
  1565. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  1566. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  1567. return(DATA_ERROR);
  1568. }
  1569. break;
  1570. case(INPUT_ORIGCHANS+4):
  1571. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  1572. sprintf(errstr,"Cannot read origchans sent from TK\n");
  1573. return(DATA_ERROR);
  1574. }
  1575. break;
  1576. case(INPUT_SPECENVCNT+4):
  1577. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  1578. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  1579. return(DATA_ERROR);
  1580. }
  1581. dz->specenvcnt = dz->infile->specenvcnt;
  1582. break;
  1583. case(INPUT_WANTED+4):
  1584. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  1585. sprintf(errstr,"Cannot read wanted sent from TK\n");
  1586. return(DATA_ERROR);
  1587. }
  1588. break;
  1589. case(INPUT_WLENGTH+4):
  1590. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  1591. sprintf(errstr,"Cannot read wlength sent from TK\n");
  1592. return(DATA_ERROR);
  1593. }
  1594. break;
  1595. case(INPUT_OUT_CHANS+4):
  1596. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  1597. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  1598. return(DATA_ERROR);
  1599. }
  1600. break;
  1601. /* RWD these chanegs to samps - tk will have to deal with that! */
  1602. case(INPUT_DESCRIPTOR_BYTES+4):
  1603. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  1604. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  1605. return(DATA_ERROR);
  1606. }
  1607. break;
  1608. case(INPUT_IS_TRANSPOS+4):
  1609. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  1610. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  1611. return(DATA_ERROR);
  1612. }
  1613. break;
  1614. case(INPUT_COULD_BE_TRANSPOS+4):
  1615. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  1616. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  1617. return(DATA_ERROR);
  1618. }
  1619. break;
  1620. case(INPUT_COULD_BE_PITCH+4):
  1621. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  1622. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  1623. return(DATA_ERROR);
  1624. }
  1625. break;
  1626. case(INPUT_DIFFERENT_SRATES+4):
  1627. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  1628. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  1629. return(DATA_ERROR);
  1630. }
  1631. break;
  1632. case(INPUT_DUPLICATE_SNDS+4):
  1633. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  1634. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  1635. return(DATA_ERROR);
  1636. }
  1637. break;
  1638. case(INPUT_BRKSIZE+4):
  1639. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  1640. sprintf(errstr,"Cannot read brksize sent from TK\n");
  1641. return(DATA_ERROR);
  1642. }
  1643. if(inbrksize > 0) {
  1644. switch(dz->input_data_type) {
  1645. case(WORDLIST_ONLY):
  1646. break;
  1647. case(PITCH_AND_PITCH):
  1648. case(PITCH_AND_TRANSPOS):
  1649. case(TRANSPOS_AND_TRANSPOS):
  1650. dz->tempsize = inbrksize;
  1651. break;
  1652. case(BRKFILES_ONLY):
  1653. case(UNRANGED_BRKFILE_ONLY):
  1654. case(DB_BRKFILES_ONLY):
  1655. case(ALL_FILES):
  1656. case(ANY_NUMBER_OF_ANY_FILES):
  1657. if(dz->extrabrkno < 0) {
  1658. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  1659. return(DATA_ERROR);
  1660. }
  1661. if(dz->brksize == NULL) {
  1662. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  1663. return(PROGRAM_ERROR);
  1664. }
  1665. dz->brksize[dz->extrabrkno] = inbrksize;
  1666. break;
  1667. default:
  1668. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  1669. dz->input_data_type);
  1670. return(PROGRAM_ERROR);
  1671. }
  1672. break;
  1673. }
  1674. break;
  1675. case(INPUT_NUMSIZE+4):
  1676. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  1677. sprintf(errstr,"Cannot read numsize sent from TK\n");
  1678. return(DATA_ERROR);
  1679. }
  1680. break;
  1681. case(INPUT_LINECNT+4):
  1682. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  1683. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  1684. return(DATA_ERROR);
  1685. }
  1686. break;
  1687. case(INPUT_ALL_WORDS+4):
  1688. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  1689. sprintf(errstr,"Cannot read all_words sent from TK\n");
  1690. return(DATA_ERROR);
  1691. }
  1692. break;
  1693. case(INPUT_ARATE+4):
  1694. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  1695. sprintf(errstr,"Cannot read arate sent from TK\n");
  1696. return(DATA_ERROR);
  1697. }
  1698. break;
  1699. case(INPUT_FRAMETIME+4):
  1700. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  1701. sprintf(errstr,"Cannot read frametime sent from TK\n");
  1702. return(DATA_ERROR);
  1703. }
  1704. dz->frametime = (float)dummy;
  1705. break;
  1706. case(INPUT_WINDOW_SIZE+4):
  1707. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  1708. sprintf(errstr,"Cannot read window_size sent from TK\n");
  1709. return(DATA_ERROR);
  1710. }
  1711. break;
  1712. case(INPUT_NYQUIST+4):
  1713. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  1714. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  1715. return(DATA_ERROR);
  1716. }
  1717. break;
  1718. case(INPUT_DURATION+4):
  1719. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  1720. sprintf(errstr,"Cannot read duration sent from TK\n");
  1721. return(DATA_ERROR);
  1722. }
  1723. break;
  1724. case(INPUT_MINBRK+4):
  1725. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  1726. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  1727. return(DATA_ERROR);
  1728. }
  1729. break;
  1730. case(INPUT_MAXBRK+4):
  1731. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  1732. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  1733. return(DATA_ERROR);
  1734. }
  1735. break;
  1736. case(INPUT_MINNUM+4):
  1737. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  1738. sprintf(errstr,"Cannot read minnum sent from TK\n");
  1739. return(DATA_ERROR);
  1740. }
  1741. break;
  1742. case(INPUT_MAXNUM+4):
  1743. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  1744. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  1745. return(DATA_ERROR);
  1746. }
  1747. break;
  1748. default:
  1749. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  1750. return(PROGRAM_ERROR);
  1751. }
  1752. cnt++;
  1753. }
  1754. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  1755. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  1756. return(DATA_ERROR);
  1757. }
  1758. if(true_cnt)
  1759. cnt = true_cnt;
  1760. *cmdlinecnt = 0;
  1761. while(cnt < argc) {
  1762. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  1763. return(exit_status);
  1764. cnt++;
  1765. }
  1766. return(FINISHED);
  1767. }
  1768. /********************************* GET_TK_CMDLINE_WORD *********************************/
  1769. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  1770. {
  1771. if(*cmdlinecnt==0) {
  1772. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  1773. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1774. return(MEMORY_ERROR);
  1775. }
  1776. } else {
  1777. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  1778. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1779. return(MEMORY_ERROR);
  1780. }
  1781. }
  1782. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  1783. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  1784. return(MEMORY_ERROR);
  1785. }
  1786. strcpy((*cmdline)[*cmdlinecnt],q);
  1787. (*cmdlinecnt)++;
  1788. return(FINISHED);
  1789. }
  1790. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  1791. int assign_file_data_storage(int infilecnt,dataptr dz)
  1792. {
  1793. int exit_status;
  1794. int no_sndfile_system_files = FALSE;
  1795. dz->infilecnt = infilecnt;
  1796. if((exit_status = allocate_filespace(dz))<0)
  1797. return(exit_status);
  1798. if(no_sndfile_system_files)
  1799. dz->infilecnt = 0;
  1800. return(FINISHED);
  1801. }
  1802. /************************* redundant functions: to ensure libs compile OK *******************/
  1803. int assign_process_logic(dataptr dz)
  1804. {
  1805. return(FINISHED);
  1806. }
  1807. void set_legal_infile_structure(dataptr dz)
  1808. {}
  1809. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  1810. {
  1811. return(FINISHED);
  1812. }
  1813. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1814. {
  1815. return(FINISHED);
  1816. }
  1817. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1818. {
  1819. return(FINISHED);
  1820. }
  1821. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1822. {
  1823. return(FINISHED);
  1824. }
  1825. int read_special_data(char *str,dataptr dz)
  1826. {
  1827. return(FINISHED);
  1828. }
  1829. int inner_loop
  1830. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1831. {
  1832. return(FINISHED);
  1833. }
  1834. /********************************************************************************************/
  1835. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1836. {
  1837. if (!strcmp(prog_identifier_from_cmdline,"specfnu")) dz->process = SPECFNU;
  1838. else {
  1839. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  1840. return(USAGE_ONLY);
  1841. }
  1842. return(FINISHED);
  1843. }
  1844. /******************************** USAGE1 ********************************/
  1845. int usage1(void)
  1846. {
  1847. usage2("specfnu");
  1848. return(USAGE_ONLY);
  1849. }
  1850. /******************************** USAGE2 ********************************/
  1851. int usage2(char *str)
  1852. {
  1853. if(!strcmp(str,"specfnu")) {
  1854. fprintf(stdout,"\n"
  1855. "USAGE: specfnu specfnu 1-9 inanalfile outfile [params]\n"
  1856. "\n"
  1857. "Modify spectral shape in relation to formant peaks, or show formant data.\n"
  1858. "\n"
  1859. "MODE 1: NARROW FORMANTS: Steepen skirts of formant peaks by power factor.\n"
  1860. "MODE 2: SQUEEZE SPECTRUM: Squeeze the spectrum around specified formant.\n"
  1861. "MODE 3: INVERT FORMANTS: Formant peaks become troughs, and troughs peaks.\n"
  1862. "MODE 4: ROTATE FORMANTS: Formant peaks & frqs move up (or down) spectrum\n"
  1863. " reappearing at foot(top) on reaching fmnts edge.\n"
  1864. "MODE 5: SPECTRAL NEGATIVE: Spectral values inverted for each channel.\n"
  1865. "MODE 6: SUPPRESS FORMANTS: Suppresses the selected formant(s).\n"
  1866. "MODE 7: GENERATE FILTER: Output Varibank filtdata based on formant peaks.\n"
  1867. "MODE 8: MOVE FORMANTS BY: Displace individual formants by a Hz value.\n"
  1868. "MODE 9: MOVE FORMANTS TO: Displace individual formants to specified frqs.\n"
  1869. "MODE 10: ARPEGGIATE: Arppegiate partials of sound, under formants.\n"
  1870. "MODE 11: OCTAVE-SHIFT: Octave-shift pitch of sound, under formants.\n"
  1871. "MODE 12: TRANSPOSE: Transpose pitch of sound, under formants.\n"
  1872. "MODE 13: FREQ-SHIFT: Frequency shift partials of src, under formants.\n"
  1873. "MODE 14: RESPACE PARTIALS: Respace partials of sound, under formants.\n"
  1874. "MODE 15: PITCH-INVERT: Invert pitch of sound, under formants.\n"
  1875. "MODE 16: PITCH-EXAGG/SMOOTH: Exaggerate/Smooth pitchline, under formants.\n"
  1876. "MODE 17: PITCH-QUANTISE: Force pitch onto pitch field, under formants.\n"
  1877. "MODE 18: PITCH-RANDOMISE: Randomise pitch of src, under formants.\n"
  1878. "MODE 19: RANDOMISE PARTIALS: Random shift partials of sound, under formants.\n"
  1879. "MODE 20: SEE SPEC ENVELOPES: Outputs viewable (not playable) sndfile.\n"
  1880. "MODE 21: SEE SPEC PEAKS/TROFS:Print textfile of frqs of peaks+trofs per window.\n"
  1881. "MODE 22: GET LOUDNESS TROFS: Print textfile of times-of-trofs between syllabs.\n"
  1882. "MODE 23: SINE SPEECH: Single sine wave repesenting each formant.\n"
  1883. "\n"
  1884. "Type \"specfnu specfnu 1\" for more info on NARROW FORMANTS.... etc.\n"
  1885. "\n"
  1886. "Spectral window-size: Small window or Large window ???\n"
  1887. "\n"
  1888. "If process uses \"Force fundamental\" flag, Large window will find fundamental\n"
  1889. "whereas Small window may not.\n");
  1890. } else
  1891. fprintf(stdout,"Unknown option '%s'\n",str);
  1892. return(USAGE_ONLY);
  1893. }
  1894. /******************************** USAGE3 ********************************/
  1895. int usage3(char *str1,char *str2)
  1896. {
  1897. if(!strcmp(str2,"1")) {
  1898. fprintf(stdout,"\n"
  1899. "MODE 1: NARROW FORMANTS: Steepens skirts of formant peaks by power factor.\n"
  1900. "\n"
  1901. "USAGE: specfnu specfnu 1 inanalfil outanalfil narrow\n"
  1902. " [-ggain] [-ooff] [-t] [-f] [-s] [-x|-k] [-r]\n"
  1903. "\n"
  1904. "NARROW Narrowing of individual formant peaks. Range 1 to 1000. Timevariable.\n"
  1905. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1906. "OFF Suppress the listed formants. \"OFF\" can be any combination of\n"
  1907. " \"1\",\"2\",\"3\" & \"4\" but not all of them, and with no repetitions.\n"
  1908. "-t Zero top of spectrum (above fourth formant).\n"
  1909. "-f Force lowest formant to use fundamental frq as peak.\n"
  1910. "-s Use short-window for extracting spectral envelope.\n"
  1911. "-x Exclude non-harmonic partials.\n"
  1912. "-k Kill harmonic partials.\n"
  1913. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1914. } else if(!strcmp(str2,"2")) {
  1915. fprintf(stdout,"\n"
  1916. "MODE 2: SQUEEZE SPECTRUM AROUND FORMANT: Squeeze around specified formant.\n"
  1917. "\n"
  1918. "USAGE: specfnu specfnu 2 inanal outanal squeeze centre\n"
  1919. " [-ggain] [-t] [-f] [-s] [-x|-k] [-r]\n"
  1920. "\n"
  1921. "SQUEEZE Squeeze factor. Range 1 to 10. Timevariable.\n"
  1922. "CENTRE Formant peak at centre of squeeze. (range 1 to 4)\n"
  1923. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1924. "-t Squeeze around trough above specified peak.\n"
  1925. "-f Force lowest formant to use fundamental frq as peak.\n"
  1926. "-s Use short-window for extracting spectral envelope.\n"
  1927. "-x Exclude non-harmonic partials.\n"
  1928. "-k Kill harmonic partials.\n"
  1929. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1930. } else if(!strcmp(str2,"3")) {
  1931. fprintf(stdout,"\n"
  1932. "MODE 3: INVERT FORMANTS: Formant peaks become troughs, and troughs peaks.\n"
  1933. "\n"
  1934. "USAGE: specfnu specfnu 3 inanal outanal vibrate [-ggain] [-s] [-x|-k] [-r]\n"
  1935. "\n"
  1936. "VIBRATE If not zero, cycle btwn orig & inverted at this frq. Timevariable.\n"
  1937. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1938. "-s Use short-window for extracting spectral envelope.\n"
  1939. "-x Exclude non-harmonic partials.\n"
  1940. "-k Kill harmonic partials.\n"
  1941. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1942. } else if(!strcmp(str2,"4")) {
  1943. fprintf(stdout,"\n"
  1944. "MODE 4: ROTATE FORMANTS: Formant peaks & frqs move up (or down) spectrum.\n"
  1945. " reappearing at foot (top) of formant-area, when they reach its edge.\n"
  1946. "\n"
  1947. "USAGE: specfnu specfnu 4 inanal outanal rspeed [-ggain] [-s] [-x|-k] [-r]\n"
  1948. "\n"
  1949. "RSPEED How quickly the spectrum rotates, e.g. 2 = twice every second.\n"
  1950. " Range -300 to 300 rotations per second. Timevariable.\n"
  1951. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1952. "-s Use short-window for extracting spectral envelope.\n"
  1953. "-x Exclude non-harmonic partials.\n"
  1954. "-k Kill harmonic partials.\n"
  1955. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1956. } else if(!strcmp(str2,"5")) {
  1957. fprintf(stdout,"\n"
  1958. "MODE 5: SPECTRAL NEGATIVE: Spectral values inverted for each channel.\n"
  1959. "\n"
  1960. "USAGE: specfnu specfnu 5 inanal outanal [-ggain] [-f]\n"
  1961. "\n"
  1962. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1963. "-f \"Flat\" : does not re-envelope the output spectrum.\n");
  1964. } else if(!strcmp(str2,"6")) {
  1965. fprintf(stdout,"\n"
  1966. "MODE 6: SUPPRESS FORMANTS: Suppresses the selected formants.\n"
  1967. "\n"
  1968. "USAGE: specfnu specfnu 6 inanalfile outanalfile formantlist [-ggain] [-s] [-x]\n"
  1969. "\n"
  1970. "FORMANTLIST which of (4) formants to suppress. e.g. \"1\" means suppress 1st,\n"
  1971. " while \"134\" means suppress 1st, 3rd and 4th.\n"
  1972. "GAIN Amplitude gain attenuation. (Range 0.1 to 10).\n"
  1973. "-s Use short-window for extracting spectral envelope.\n"
  1974. "-x Exclude non-harmonic partials.\n");
  1975. } else if(!strcmp(str2,"7")) {
  1976. fprintf(stdout,"\n"
  1977. "MODE 7: GENERATE FILTER(S) FROM FORMANT(S): Outputs varibank filter data textfile.\n"
  1978. "\n"
  1979. "USAGE: specfnu specfnu 7 inanalfile outfiltfile datafile filtcnt\n"
  1980. " [-bbelow] [-k|-i] [-f] [-s]\n"
  1981. "\n"
  1982. "DATAFILE Textfile containing.\n"
  1983. " (1) List of times at which src to be divided into blocks for analysis.\n"
  1984. " Resulting filter step-changes between vals created from each block.\n"
  1985. " Value ZERO means use the entire source to make 1 fixed filter.\n"
  1986. " (2) Data about grid on which pitches you are searching for must lie.\n"
  1987. " There must first be a marker indicating the grid type. These are..\n"
  1988. " #HS: Followed by listed MIDI pitches to search for.\n"
  1989. " #HF: Followed by listed MIDI pitches to search for IN ALL OCTAVES.\n"
  1990. " #SCALE: Followed by just TWO values.\n"
  1991. " (a) the number of equal pitch divisions in an octave.\n"
  1992. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  1993. " #ELACS: Followed by just THREE values.\n"
  1994. " (a) Size of \"octave\" in (possibly fractional) semitones.\n"
  1995. " (b) the number of equal pitch divisions in \"octave\".\n"
  1996. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  1997. "FILTCNT (Default value 1). (Max) No. peaks from each formant to use.\n"
  1998. "BELOW Try to ensure 1 (or more) pitches below MIDI value \"below\".\n"
  1999. "-k Keep relative (summed) loudnesses of peaks as part of filter design.\n"
  2000. "-i Keep inverse of loudnesses as part of filter design.\n"
  2001. " Default. All filter amplitudes set to 1.0\n"
  2002. "-f Force fundamental as pitch in lowest formant.\n"
  2003. "-s Use short-window for extracting spectral envelope.\n"
  2004. "\n"
  2005. "With time-varying filter, transitions between time blocks can be extreme.\n"
  2006. "Wise to cut input into segments and produce fixed filters for each,\n"
  2007. "OR pre-envelope THE input file, to zero the level around transitions\n"
  2008. "deriving appropriate envelope times from the filter file times.\n");
  2009. } else if(!strcmp(str2,"8")) {
  2010. fprintf(stdout,"\n"
  2011. "MODE 8: MOVE FORMANTS BY: Displace individual formants.\n"
  2012. "\n"
  2013. "USAGE: specfnu specfnu 8 inanal outanal mov1 mov2 mov3 mov4\n"
  2014. " [-ggain] [-t] [-s] [-x|-k] [-r]\n"
  2015. "\n"
  2016. "MOV1 Frq displacement, up or down, of formant 1. Timevariable.\n"
  2017. "MOV2,3,4 Similarly for other formants.\n"
  2018. "(Formants moving below zero or above nyquist/2 will disappear).\n"
  2019. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2020. "-t Zero top of spectrum.\n"
  2021. "-s Use short-window for extracting spectral envelope.\n"
  2022. "-x Exclude non-harmonic partials.\n"
  2023. "-k Kill harmonic partials.\n"
  2024. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  2025. } else if(!strcmp(str2,"9")) {
  2026. fprintf(stdout,"\n"
  2027. "MODE 9: MOVE FORMANTS TO: Displace individual formants.\n"
  2028. "\n"
  2029. "USAGE: specfnu specfnu 9 inanal outanal frq1 frq2 frq2 frq4\n"
  2030. " [-ggain] [-t] [-s] [-n] [-x|-k] [-r]\n"
  2031. "\n"
  2032. "FRQ1 New frq of formant 1. Timevariable.\n"
  2033. "FRQ2,3,4 Similarly for other formants.\n"
  2034. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2035. "-t Zero top of spectrum.\n"
  2036. "-n Use narrow formant bands.\n"
  2037. " Using narrow bands can give counterintuitive results.\n"
  2038. " Doesn't capture so many harmonic peaks, so sounds duller.\n"
  2039. "-s Use short-window for extracting spectral envelope.\n"
  2040. "-x Exclude non-harmonic partials.\n"
  2041. "-k Kill harmonic partials.\n"
  2042. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  2043. } else if(!strcmp(str2,"10")) {
  2044. fprintf(stdout,"\n"
  2045. "MODE 10: ARPEGGIATE SPECTRUM: Arpeggiate spectrum of source, under formants.\n"
  2046. "\n"
  2047. "USAGE: specfnu specfnu 10 inanal outanal arprate\n"
  2048. " [-ggain] [-s] [-x] [-r] [-d|-c]\n"
  2049. "\n"
  2050. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2051. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2052. "-s Use short-window for extracting spectral envelope.\n"
  2053. "-x Exclude non-harmonic partials.\n"
  2054. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2055. "-d Arpeggiate downwards (default upwards).\n"
  2056. "-c Arpeggiate up and down (default upwards).\n");
  2057. } else if(!strcmp(str2,"11")) {
  2058. fprintf(stdout,"\n"
  2059. "MODE 11: OCTAVE-SHIFT UNDER FORMANTS: Octave-shift src spectrum, under formants.\n"
  2060. "\n"
  2061. "USAGE: specfnu specfnu 11 inanal outanal octshift \n"
  2062. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2063. "\n"
  2064. "OCTSHIFT 8va shift (Range -4 to + 4). (Timevariable).\n"
  2065. "\n"
  2066. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2067. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2068. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2069. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2070. "-s Use short-window for extracting spectral envelope.\n"
  2071. "-x Exclude non-harmonic partials.\n"
  2072. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2073. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2074. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2075. "-f If transposing downwards, fill spectrum top with extra harmonics.\n");
  2076. } else if(!strcmp(str2,"12")) {
  2077. fprintf(stdout,"\n"
  2078. "MODE 12: TRANSPOSE UNDER FORMANTS: tranpose spectrum of src, under formants.\n"
  2079. "\n"
  2080. "USAGE: specfnu specfnu 12 inanal outanal transpos \n"
  2081. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2082. "\n"
  2083. "TRANSPOS semitone shift (Range -48 to + 48). (Timevariable).\n"
  2084. "\n"
  2085. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2086. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2087. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2088. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2089. "-s Use short-window for extracting spectral envelope.\n"
  2090. "-x Exclude non-harmonic partials.\n"
  2091. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2092. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2093. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2094. "-f If transposing downwards, fill spectrum top with extra harmonics.\n");
  2095. } else if(!strcmp(str2,"13")) {
  2096. fprintf(stdout,"\n"
  2097. "MODE 13: FRQSHIFT UNDER FORMANTS: Frqshift src spectrum of under formants.\n"
  2098. "\n"
  2099. "USAGE: specfnu specfnu 13 inanal outanal frqshift\n"
  2100. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2101. "\n"
  2102. "FRQSHIFT Frequency shift(Hz) (Range -1000 to +1000). (Timevariable).\n"
  2103. "\n"
  2104. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2105. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2106. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2107. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2108. "-s Use short-window for extracting spectral envelope.\n"
  2109. "-x Exclude non-harmonic partials.\n"
  2110. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2111. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2112. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2113. "-f If shifting down, fill spectrum top with extra shifted partials.\n");
  2114. } else if(!strcmp(str2,"14")) {
  2115. fprintf(stdout,"\n"
  2116. "MODE 14: RESPACE PARTIALS UNDER FORMANTS: Respace partials in src spectrum,\n"
  2117. " retaining formants.\n"
  2118. "\n"
  2119. "USAGE: specfnu specfnu 14 inanal outanal respace\n"
  2120. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2121. "\n"
  2122. "RESPACE New frq spacing of partials (Hz) (Range 1 to 1000).\n"
  2123. " (Timevariable).\n"
  2124. "\n"
  2125. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2126. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2127. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2128. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2129. "-s Use short-window for extracting spectral envelope.\n"
  2130. "-x Exclude non-harmonic partials.\n"
  2131. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2132. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2133. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2134. "-f If narrowed spacing, fill spectrum top with extra shifted partials.\n");
  2135. } else if(!strcmp(str2,"15")) {
  2136. fprintf(stdout,"\n"
  2137. "MODE 15: PITCH-INVERT UNDER FORMANTS: Invert pitch of src, under formants.\n"
  2138. "\n"
  2139. "USAGE: specfnu specfnu 15 inanal outanal map about [-ggain] [-parprate]\n"
  2140. " [-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c]\n"
  2141. "\n"
  2142. "MAP Set map to ZERO if no mapping is required..OTHERWISE\n"
  2143. " map is a textfile of paired values showing how intervals\n"
  2144. " (in, possibly fractional, SEMITONES)\n"
  2145. " are to be mapped onto their inversions.\n"
  2146. " Range +-%0lf semitones (+- %.0lf octaves).\n"
  2147. "\n"
  2148. "ABOUT Pitch about which to invert pitch of src (Range %d to %d).\n"
  2149. " Pitch as MIDI, with possibly fractional val. (Timevariable).\n"
  2150. " If value zero entered, uses the mean pitch of the input.\n"
  2151. "\n"
  2152. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2153. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2154. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2155. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2156. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2157. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2158. "-s Use short-window for extracting spectral envelope.\n"
  2159. "-x Exclude non-harmonic partials.\n"
  2160. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2161. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2162. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n",MAXINTRANGE,MAXINTRANGE/SEMITONES_PER_OCTAVE,SPEC_MIDIMIN,MIDIMAX);
  2163. } else if(!strcmp(str2,"16")) {
  2164. fprintf(stdout,"\n"
  2165. "MODE 16: PITCH-EXAGGERATE/SMOOTH UNDER FORMANTS: Exaggerate/Smooth pitch-line,\n"
  2166. " retaining the formants.\n"
  2167. "\n"
  2168. "USAGE: specfnu specfnu 16 inanal outanal about rang [-ggain] [-parprate]\n"
  2169. " [-llocut] [-hhicut] [-blopch] [-thipch] [-T] [-F] [-M] [-A] [-B]\n"
  2170. " [-s] [-x] [-r] [-d|-c]\n"
  2171. "\n"
  2172. "ABOUT Pitch about which to exagg/smooth pitchline of src (Range %d to %d).\n"
  2173. " Pitch as MIDI, with possibly fractional val. (Timevariable).\n"
  2174. " If value zero entered, uses the mean pitch of the input.\n"
  2175. "RANG Expand or Contract Range of pitchline. (Range 0 - 1).\n"
  2176. "\n"
  2177. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2178. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2179. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2180. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2181. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2182. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2183. "-T Tie to TOP of pitch range.\n"
  2184. "-F Tie to FOOT of pitch range.\n"
  2185. "-M (only with \"-T\" and \"M\" flags) also Tie to range middle.\n"
  2186. "-A Do range change ABOVE mean only.\n"
  2187. "-B Do range change BELOW mean only.\n"
  2188. "-s Use short-window for extracting spectral envelope.\n"
  2189. "-x Exclude non-harmonic partials.\n"
  2190. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2191. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2192. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n",SPEC_MIDIMIN,MIDIMAX);
  2193. } else if(!strcmp(str2,"17")) {
  2194. fprintf(stdout,"\n"
  2195. "MODE 17: QUANTISE PITCH: Force source onto a specified pitch field.\n"
  2196. "\n"
  2197. "USAGE: specfnu specfnu 17 inanal outanal datafile [-ggain] [-parprate]\n"
  2198. " [-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c] [-o] [-n]\n"
  2199. "\n"
  2200. "DATAFILE Textfile containing data about pitches to quantise to.\n"
  2201. " There must first be a marker indicating the grid type. These are..\n"
  2202. " #HS: Followed by listed MIDI pitches to quantise to.\n"
  2203. " #HF: Followed by listed MIDI pitches to quantise to IN ALL OCTAVES.\n"
  2204. " #THF: Followed by lines each with time + list of MIDI pitches.\n"
  2205. " 1st time must be zero & times must increase.\n"
  2206. " Each MIDI list must be the same length.\n"
  2207. " To change no of pitches from line to line, duplicate values.\n"
  2208. " #SCALE: Followed by just TWO values.\n"
  2209. " (a) the number of equal pitch divisions in an octave.\n"
  2210. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2211. " #ELACS: Followed by just THREE values.\n"
  2212. " (a) Size of \"pseudo-octave\" in (possibly fractional) semitones.\n"
  2213. " (b) the number of equal pitch divisions in peudo-octave.\n"
  2214. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2215. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2216. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2217. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2218. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2219. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2220. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2221. "-s Use short-window for extracting spectral envelope.\n"
  2222. "-x Exclude non-harmonic partials.\n"
  2223. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2224. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2225. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2226. "-o Allow ORNAMENTS in the quantised pitch-line.\n"
  2227. "-n No smoothing of transitions between pitches.\n");
  2228. } else if(!strcmp(str2,"18")) {
  2229. fprintf(stdout,"\n"
  2230. "MODE 18: PITCH RANDOMISE: Randomise pitch of src.\n"
  2231. "\n"
  2232. "USAGE: specfnu specfnu 18 inanal outanal datafile range slew [-ggain] [-parprate]\n"
  2233. " [-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c] [-o] [-n] [-k]]\n"
  2234. "\n"
  2235. "DATAFILE If this set to ZERO, no pre-quantisation of pitch takes place.\n"
  2236. " Otherwise, this is textfile of data about pitches to quantise to.\n"
  2237. " There must first be a marker indicating the grid type. These are..\n"
  2238. " #HS: Followed by listed MIDI pitches to quantise to.\n"
  2239. " #HF: Followed by listed MIDI pitches to quantise to IN ALL OCTAVES.\n"
  2240. " #THF: Followed by lines each with time + list of MIDI pitches.\n"
  2241. " 1st time must be zero & times must increase.\n"
  2242. " Each MIDI list must be the same length.\n"
  2243. " To change no of pitches from line to line, duplicate values.\n"
  2244. " #SCALE: Followed by just TWO values.\n"
  2245. " (a) the number of equal pitch divisions in an octave.\n"
  2246. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2247. " #ELACS: Followed by just THREE values.\n"
  2248. " (a) Size of \"pseudo-octave\" in (possibly fractional) semitones.\n"
  2249. " (b) the number of equal pitch divisions in peudo-octave.\n"
  2250. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2251. "RANGE semitone range within which random offsets generated. (Range 0 to %d)\n"
  2252. "SLEW Relationship between (possible) upward & downward rand variation.\n"
  2253. " e.g. 2: uprange = 2 * downrange 0.5: uprange = 0.5 * downrange.\n"
  2254. " Ranges 0.1 to 10. (Value 1 has no effect).\n"
  2255. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2256. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2257. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2258. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2259. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2260. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2261. "-s Use short-window for extracting spectral envelope.\n"
  2262. "-x Exclude non-harmonic partials.\n"
  2263. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2264. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2265. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2266. "-o Open up FAST MOVEMENT in the quantised pitch-line.\n"
  2267. "-n No smoothing of transitions between pitches.\n"
  2268. "-k Kill-off formant reshaping.\n",RANDPITCHMAX);
  2269. } else if(!strcmp(str2,"19")) {
  2270. fprintf(stdout,"\n"
  2271. "MODE 19: RANDOMISE SPECTRUM UNDER FORMANTS: Randomise spectrum, under formants.\n"
  2272. "\n"
  2273. "USAGE: specfnu specfnu 19 inanal outanal rand\n"
  2274. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n"
  2275. "\n"
  2276. "RAND Randomisation of partial frequencies (Range 0 to 1).\n"
  2277. " (Timevariable).\n"
  2278. "\n"
  2279. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2280. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2281. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2282. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2283. "-s Use short-window for extracting spectral envelope.\n"
  2284. "-x Exclude non-harmonic partials.\n"
  2285. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2286. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2287. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n");
  2288. } else if(!strcmp(str2,"20")) {
  2289. fprintf(stdout,"\n"
  2290. "MODE 20: SEE SPECTRAL ENVELOPES: Outputs viewable (not playable) sndfile\n"
  2291. " showing spectral envelope at each window\n"
  2292. " as a block of +ve samples.\n"
  2293. "\n"
  2294. "USAGE: specfnu specfnu 20 inanalfile outpseudosndfile [-s]\n"
  2295. "\n"
  2296. "-s Use short-window for extracting spectral envelope.\n");
  2297. } else if(!strcmp(str2,"21")) {
  2298. fprintf(stdout,"\n"
  2299. "MODE 21: SEE SPECTRAL PEAKS & TROUGHS: Frqs of troughs/peaks in each window\n"
  2300. " printed to textfile, in the format...\n"
  2301. "\n"
  2302. " \"Trough PEAK-1 Trough PEAK-2 Trough PEAK-3 Trough PEAK-4 Trough\"\n"
  2303. "\n"
  2304. "USAGE: specfnu specfnu 21 inanalfile outtextfile [-s]\n"
  2305. "\n"
  2306. "-s Use short-window for extracting spectral envelope.\n");
  2307. } else if(!strcmp(str2,"22")) {
  2308. fprintf(stdout,"\n"
  2309. "MODE 22: LIST TIMES OF TROUGHS BETWEEN SYLLABLES: Times printed to textfile.\n"
  2310. "\n"
  2311. "Will usually need post-correction \"by hand\".\n"
  2312. "\n"
  2313. "USAGE: specfnu specfnu 22 inanal outtextfile [-ssyldur] [-ppktrof] [-P|-B]\n"
  2314. "\n"
  2315. "SYLDUR Min acceptable duration for a syllable (default %.04lf)\n"
  2316. "PKTROF Min height of peak above bracketing trofs (default %.04lf).\n"
  2317. " (Maximum possible height is 1.0).\n"
  2318. "-P Get peaks.\n"
  2319. "-B Get both troughs and peaks,\n",MIN_SYLLAB_DUR,MIN_PEAKTROF_GAP);
  2320. } else if(!strcmp(str2,"23")) {
  2321. fprintf(stdout,"\n"
  2322. "MODE 23: SINE SPEECH: Convert formant frqs to sinus tones.\n"
  2323. "\n"
  2324. "USAGE: specfnu specfnu 23 inanalfile outanalfile hffile sining [-again]\n"
  2325. "[-bamp1] [-camp2] [-damp3] [-eamp4] [-nqdep1] [-oqdep2] [-pdep3] [-qqdep4]\n"
  2326. "[-s] [-f] [-r] [-S]\n"
  2327. "\n"
  2328. "HFFILE If this set to ZERO, no pitch quantisation takes place.\n"
  2329. " Otherwise, this is textfile of data about pitches to quantise to.\n"
  2330. " There must first be a marker indicating the grid type. These are..\n"
  2331. " #HS: Followed by listed MIDI pitches to quantise to.\n"
  2332. " #HF: Followed by listed MIDI pitches to quantise to IN ALL OCTAVES.\n"
  2333. " #THF: Followed by lines each with time + list of MIDI pitches.\n"
  2334. " 1st time must be zero & times must increase.\n"
  2335. " Each MIDI list must be the same length.\n"
  2336. " To change no of pitches from line to line, duplicate values.\n"
  2337. " #SCALE: Followed by just TWO values.\n"
  2338. " (a) the number of equal pitch divisions in an octave.\n"
  2339. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2340. " #ELACS: Followed by just THREE values.\n"
  2341. " (a) Size of \"pseudo-octave\" in (possibly fractional) semitones.\n"
  2342. " (b) the number of equal pitch divisions in peudo-octave.\n"
  2343. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2344. "\n"
  2345. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2346. "SINING Degree of sinusoidisation. Range 0 to 1.\n"
  2347. "AMP1 Relative gain or attenuation of formant1. (Range 0.01 to 10)\n"
  2348. " AMP2,AMP3,AMP4 similar for the other formants.\n"
  2349. "DEP1 If HF applied, how strongly to force pitches formant1 to hf (Range 0-1).\n"
  2350. "DEP2, DEP3, DEP4 Similarly for other formant bands.\n"
  2351. "-s Use short-window for extracting spectral envelope.\n"
  2352. "-f Force lowest formant to use fundamental frq as peak.\n"
  2353. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2354. "-S Smoothing between pitches in formant traces.\n");
  2355. } else
  2356. fprintf(stdout,"Unknown mode '%s'\n",str2);
  2357. return(USAGE_ONLY);
  2358. }
  2359. /******************************** USAGE4 ********************************/
  2360. int usage4(int mode)
  2361. {
  2362. fprintf(stdout,"\nToo few parameters ");
  2363. switch(mode) {
  2364. case(0):
  2365. fprintf(stdout,"NARROW FORMANTS\n\n");
  2366. fprintf(stdout,"USAGE: specfnu specfnu 1 inanal outanal narrow\n");
  2367. fprintf(stdout,"[-ggain] [-ooff] [-t] [-f] [-s] [-x|-k] [-r]\n");
  2368. break;
  2369. case(1):
  2370. fprintf(stdout,"SQUEEZE SPECTRUM AROUND FORMANT\n\n");
  2371. fprintf(stdout,"USAGE: specfnu specfnu 2 inanal outanal squeeze centre\n");
  2372. fprintf(stdout,"[-ggain] [-t] [-f] [-s] [-x|-k] [-r]\n");
  2373. break;
  2374. case(2):
  2375. fprintf(stdout,"INVERT FORMANTS\n\n");
  2376. fprintf(stdout,"USAGE: specfnu specfnu 3 inanal outanal vibrate [-ggain] [-s] [-x|-k] [-r]\n");
  2377. break;
  2378. case(3):
  2379. fprintf(stdout,"ROTATE FORMANTS\n\n");
  2380. fprintf(stdout,"USAGE: specfnu specfnu 4 inanal outanal rspeed [-ggain] [-s] [-x|-k] [-r]\n");
  2381. break;
  2382. case(4):
  2383. fprintf(stdout,"SPECTRAL NEGATIVE\n\n");
  2384. fprintf(stdout,"USAGE: specfnu specfnu 5 inanal outanal [-ggain] [-f]\n");
  2385. break;
  2386. case(5):
  2387. fprintf(stdout,"SUPPRESS FORMANTS\n\n");
  2388. fprintf(stdout,"USAGE: specfnu specfnu 6 inanal outanal formantlist [-ggain] [-s] [-x]\n");
  2389. break;
  2390. case(6):
  2391. fprintf(stdout,"GENERATE FILTER(S) FROM FORMANT(S)\n\n");
  2392. fprintf(stdout,"USAGE: specfnu specfnu 7 inanal outfiltfil datafile filtcnt\n");
  2393. fprintf(stdout,"[-bbelow] [-k|-i] [-f] [-s]\n");
  2394. break;
  2395. case(7):
  2396. fprintf(stdout,"MOVE FORMANTS BY\n\n");
  2397. fprintf(stdout,"USAGE: specfnu specfnu 8 inanal outanal mov1 mov2 mov2 mov4\n");
  2398. fprintf(stdout,"[-ggain] [-t] [-s] [-x|-k] [-r]\n");
  2399. break;
  2400. case(8):
  2401. fprintf(stdout,"MOVE FORMANTS TO\n\n");
  2402. fprintf(stdout,"USAGE: specfnu specfnu 9 inanal outanal frq1 frq2 frq2 frq4\n");
  2403. fprintf(stdout,"[-ggain] [-t] [-s] [-n] [-x|-k] [-r]\n");
  2404. break;
  2405. case(9):
  2406. fprintf(stdout,"ARPEGGIATE SPECTRUM \n\n");
  2407. fprintf(stdout,"USAGE: specfnu specfnu 10 inanal outanal arprate\n");
  2408. fprintf(stdout,"[-ggain] [-s] [-x] [-r] [-d|-c]\n");
  2409. break;
  2410. case(10):
  2411. fprintf(stdout,"OCTAVE-SHIFT UNDER FORMANTS\n\n");
  2412. fprintf(stdout,"USAGE: specfnu specfnu 11 inanal outanal octshift\n");
  2413. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2414. break;
  2415. case(11):
  2416. fprintf(stdout,"TRANSPOSE UNDER FORMANTS \n\n");
  2417. fprintf(stdout,"USAGE: specfnu specfnu 12 inanal outanal transpos\n");
  2418. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2419. break;
  2420. case(12):
  2421. fprintf(stdout,"FRQSHIFT UNDER FORMANTS \n\n");
  2422. fprintf(stdout,"USAGE: specfnu specfnu 13 inanal outanal frqshift\n");
  2423. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2424. break;
  2425. case(13):
  2426. fprintf(stdout,"RESPACE PARTIALS UNDER FORMANTS \n\n");
  2427. fprintf(stdout,"USAGE: specfnu specfnu 14 inanal outanal respace\n");
  2428. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2429. break;
  2430. case(14):
  2431. fprintf(stdout,"PITCH INVERT UNDER FORMANTS \n\n");
  2432. fprintf(stdout,"USAGE: specfnu specfnu 15 inanal outanal about\n");
  2433. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n");
  2434. break;
  2435. case(15):
  2436. fprintf(stdout,"PITCH EXAGGERATE UNDER FORMANTS \n\n");
  2437. fprintf(stdout,"USAGE: specfnu specfnu 16 inanal outanal about rang [-ggain] [-parprate]\n");
  2438. fprintf(stdout,"[-llocut] [-hhicut] [-blopch] [-thipch] [-T] [-F] [-M] [-A] [-B]\n");
  2439. fprintf(stdout,"[-s] [-x] [-r] [-d|-c]\n");
  2440. break;
  2441. case(16):
  2442. fprintf(stdout,"PITCH QUANTISE UNDER FORMANTS \n\n");
  2443. fprintf(stdout,"USAGE: specfnu specfnu 17 inanal outanal datafile [-ggain] [-parprate]\n");
  2444. fprintf(stdout,"[-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c]\n");
  2445. break;
  2446. case(17):
  2447. fprintf(stdout,"RANDOMISE SPECTRUM UNDER FORMANTS \n\n");
  2448. fprintf(stdout,"USAGE: specfnu specfnu 18 inanal outanal rand\n");
  2449. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n");
  2450. break;
  2451. case(18):
  2452. fprintf(stdout,"RANDOMISE SPECTRUM UNDER FORMANTS \n\n");
  2453. fprintf(stdout,"USAGE: specfnu specfnu 19 inanal outanal rand\n");
  2454. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n");
  2455. break;
  2456. case(19):
  2457. fprintf(stdout,"SEE SPECTRAL ENVELOPES \n\n");
  2458. fprintf(stdout,"USAGE: specfnu specfnu 20 inanalfile outpseudosndfile [-s]\n");
  2459. break;
  2460. case(20):
  2461. fprintf(stdout,"SEE SPECTRAL PEAKS & TROUGHS \n\n");
  2462. fprintf(stdout,"USAGE: specfnu specfnu 21 inanalfile outtextfile [-s]\n");
  2463. break;
  2464. case(21):
  2465. fprintf(stdout,"LIST TIMES OF TROUGHS BETWEEN SYLLABLES \n\n");
  2466. fprintf(stdout,"USAGE: specfnu specfnu 22 inanal outtextfile [-ssyldur] [-ppktrof] [-P|-B]\n");
  2467. break;
  2468. case(22):
  2469. fprintf(stdout,"SINE SPEECH \n\n");
  2470. fprintf(stdout,"USAGE: specfnu specfnu 23 inanalfile outanalfile hffile sining [-again]\n");
  2471. fprintf(stdout,"[-bamp1] [-camp2] [-damp3] [-eamp4] [-nqdep1] [-oqdep2] [-pdep3] [-qqdep4]\n");
  2472. fprintf(stdout,"[-s] [-f] [-r] [-S]\n");
  2473. break;
  2474. }
  2475. fflush(stdout);
  2476. return(USAGE_ONLY);
  2477. }
  2478. /************************ GET_THE_MODE_NO *********************/
  2479. int get_the_mode_no(char *str, dataptr dz)
  2480. {
  2481. if(sscanf(str,"%d",&dz->mode)!=1) {
  2482. sprintf(errstr,"Cannot read mode of program.\n");
  2483. return(USAGE_ONLY);
  2484. }
  2485. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  2486. sprintf(errstr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  2487. return(USAGE_ONLY);
  2488. }
  2489. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  2490. return(FINISHED);
  2491. }
  2492. /************************ FORCE_EXTENSION *********************/
  2493. void force_extension(int type,char *filename)
  2494. {
  2495. char *q, *p = filename;
  2496. int doit = 0;
  2497. while(*p != '.') {
  2498. p++;
  2499. if(*p == ENDOFSTR)
  2500. break;
  2501. }
  2502. if(*p == ENDOFSTR) {
  2503. switch(type) {
  2504. case(0): strcat(filename,".wav"); break;
  2505. case(1): strcat(filename,".txt"); break;
  2506. }
  2507. } else {
  2508. p++;
  2509. q = p;
  2510. switch(type) {
  2511. case(0):
  2512. if(*q++ != 'w')
  2513. doit = 1; //RWD all 4 cases, needed assignment
  2514. else {
  2515. if(*q++ != 'a')
  2516. doit = 1;
  2517. else {
  2518. if(*q++ != 'v')
  2519. doit = 1;
  2520. else {
  2521. if(*q != ENDOFSTR)
  2522. doit = 1;
  2523. }
  2524. }
  2525. }
  2526. break;
  2527. case(1):
  2528. if(*q++ != 't')
  2529. doit = 1;
  2530. else {
  2531. if(*q++ != 'x')
  2532. doit = 1;
  2533. else {
  2534. if(*q++ != 't')
  2535. doit = 1;
  2536. else {
  2537. if(*q != ENDOFSTR)
  2538. doit = 1;
  2539. }
  2540. }
  2541. }
  2542. break;
  2543. }
  2544. if(doit) {
  2545. *p = ENDOFSTR;
  2546. switch(type) {
  2547. case(0): strcat(filename,"wav"); break;
  2548. case(1): strcat(filename,"txt"); break;
  2549. }
  2550. }
  2551. }
  2552. }
  2553. /**************************** OUTER_SPECFNU_LOOP ****************************/
  2554. int outer_specfnu_loop(int contourcnt,dataptr dz)
  2555. {
  2556. int exit_status, n, zerolen, cc, vc, passno = 0, times_index, arp_param = 0, previouspk = -1, up = 1;
  2557. int windows_in_buf, inner_lpcnt;
  2558. double thisfrq, fmax = -HUGE, normaliser = 0.0;
  2559. int limit = dz->wlength * PKBLOK;
  2560. double phase = 0.0, target = 0.0, maxpitch = 0.0, minpitch = 0.0;
  2561. // Where, in the 3 processing loops, does each mode begin
  2562. switch(dz->mode) {
  2563. case(F_ARPEG):
  2564. arp_param = FARPRATE;
  2565. passno = FPREANAL;
  2566. break;
  2567. case(F_OCTSHIFT):// fall thro
  2568. case(F_TRANS): // fall thro
  2569. case(F_FRQSHIFT):// fall thro
  2570. case(F_RESPACE): // fall thro
  2571. case(F_PINVERT): // fall thro
  2572. case(F_RAND): // fall thro
  2573. case(F_PEXAGG): // fall thro
  2574. case(F_PQUANT): // fall thro
  2575. case(F_PCHRAND):
  2576. arp_param = COLRATE;
  2577. passno = FPREANAL;
  2578. break;
  2579. case(F_SYLABTROF)://fall thro
  2580. case(F_SINUS):
  2581. passno = FPREANAL;
  2582. break;
  2583. case(F_NARROW): // fall thro
  2584. case(F_SQUEEZE):// fall thro
  2585. case(F_MOVE): // fall thro
  2586. case(F_MOVE2): // fall thro
  2587. case(F_INVERT): // fall thro
  2588. case(F_ROTATE): // fall thro
  2589. case(F_SUPPRESS):// fall thro
  2590. case(F_MAKEFILT):
  2591. if(dz->needpitch)
  2592. passno = FPREANAL; // Extract pitch data (FPREANAL) before extracting formant env FSPECENV and then processing sound FPROCESS
  2593. else
  2594. passno = FSPECENV;
  2595. break;
  2596. case(F_NEGATE):
  2597. if(dz->needpitch)
  2598. passno = FPREANAL; // Extract pitch data (FPREANAL) before processing sound FPROCESS
  2599. else
  2600. passno = FPROCESS; // Otheriwise SKIP extracting formantenv (not needed) and go dircetly to FPROCESS
  2601. break;
  2602. case(F_SEE):
  2603. passno = FSPECENV; // Extract formant env FSPECENV before processing sound FPROCESS
  2604. break;
  2605. case(F_SEEPKS):
  2606. passno = FPROCESS; // Go directly to processing sound FPROCESS
  2607. break;
  2608. }
  2609. while(passno < 3) {
  2610. /* TEST *
  2611. fprintf(stderr,"passno = %d\n",passno);
  2612. /* TEST */
  2613. // Which modes skip some of the processing loops?
  2614. if(passno > 0 && dz->mode == F_SYLABTROF) {
  2615. passno++;
  2616. continue; // F_SYLABTROF needs to get loudness envelope (during pitch-analysis routine) but needs nothing else;
  2617. }
  2618. if(passno == FSPECENV && dz->mode == F_NEGATE) {
  2619. passno++; // F_NEGATE may use pass0 (to get pitch), but doesn't need to get spectral peaks
  2620. continue;
  2621. }
  2622. times_index = 1;
  2623. inner_lpcnt = 0;
  2624. if(sloom)
  2625. dz->total_samps_read = 0L;
  2626. // Messaging
  2627. switch(passno) {
  2628. case(FPREANAL): // (pass 0) EXTRACTING PITCH, AND LOUDNESS-ENVELOPE
  2629. switch(dz->mode) {
  2630. case(F_MOVE): // fall thro
  2631. case(F_MOVE2): // fall thro
  2632. case(F_NEGATE): // fall thro
  2633. case(F_INVERT): // fall thro
  2634. case(F_NARROW): // fall thro
  2635. case(F_SQUEEZE): // fall thro
  2636. case(F_ROTATE): // fall thro
  2637. case(F_ARPEG): // fall thro
  2638. case(F_OCTSHIFT): // fall thro
  2639. case(F_TRANS): // fall thro
  2640. case(F_FRQSHIFT): // fall thro
  2641. case(F_RESPACE): // fall thro
  2642. case(F_PINVERT): // fall thro
  2643. case(F_PEXAGG): // fall thro
  2644. case(F_PQUANT): // fall thro
  2645. case(F_PCHRAND): // fall thro
  2646. case(F_SINUS): // fall thro
  2647. case(F_RAND): // fall thro
  2648. case(F_MAKEFILT): fprintf(stdout,"INFO: Extracting pitch contour.\n"); break;
  2649. case(F_SYLABTROF): fprintf(stdout,"INFO: Extracting loudness contour.\n"); break;
  2650. default:
  2651. sprintf(errstr,"Unknown mode in pass %d.\n",passno);
  2652. return PROGRAM_ERROR;
  2653. }
  2654. break;
  2655. case(FSPECENV): // (pass 1) GET SPECTRAL ENVELOPE
  2656. switch(dz->mode) {
  2657. case(F_SEE): fprintf(stdout,"INFO: Testing level.\n"); break;
  2658. case(F_SQUEEZE): // fall thro
  2659. case(F_SUPPRESS): // fall thro
  2660. case(F_INVERT): // fall thro
  2661. case(F_ROTATE): // fall thro
  2662. case(F_MAKEFILT): // fall thro
  2663. case(F_MOVE): // fall thro
  2664. case(F_MOVE2): // fall thro
  2665. case(F_SINUS): // fall thro
  2666. case(F_NARROW): fprintf(stdout,"INFO: Finding spectral peak data.\n"); break;
  2667. case(F_ARPEG): // fall thro
  2668. case(F_OCTSHIFT): // fall thro
  2669. case(F_TRANS): // fall thro
  2670. case(F_FRQSHIFT): // fall thro
  2671. case(F_RESPACE): // fall thro
  2672. case(F_PINVERT): // fall thro
  2673. case(F_PEXAGG): // fall thro
  2674. case(F_PQUANT): // fall thro
  2675. case(F_PCHRAND): // fall thro
  2676. case(F_RAND): fprintf(stdout,"INFO: Finding spectral envelope.\n"); break;
  2677. case(F_NEGATE): // fall thro
  2678. case(F_SEEPKS): // fall thro
  2679. case(F_SYLABTROF):
  2680. sprintf(errstr,"Should not be visited on this pass (%d).\n",passno);
  2681. return PROGRAM_ERROR;
  2682. default:
  2683. sprintf(errstr,"Unknown mode in pass %d.\n",passno);
  2684. return PROGRAM_ERROR;
  2685. }
  2686. break;
  2687. case(FPROCESS): // (pass 2) PROCESS SOUND
  2688. switch(dz->mode) {
  2689. case(F_SEE): // fall thro
  2690. case(F_MAKEFILT): // fall thro
  2691. case(F_SEEPKS): fprintf(stdout,"INFO: Writing output.\n"); break;
  2692. case(F_NARROW):
  2693. case(F_ROTATE):
  2694. case(F_SQUEEZE):
  2695. case(F_SUPPRESS):
  2696. case(F_INVERT):
  2697. case(F_NEGATE):
  2698. case(F_ARPEG): // fall thro
  2699. case(F_OCTSHIFT): // fall thro
  2700. case(F_TRANS): // fall thro
  2701. case(F_FRQSHIFT): // fall thro
  2702. case(F_RESPACE): // fall thro
  2703. case(F_PINVERT): // fall thro
  2704. case(F_PEXAGG): // fall thro
  2705. case(F_PQUANT): // fall thro
  2706. case(F_SINUS): // fall thro
  2707. case(F_PCHRAND): // fall thro
  2708. case(F_RAND): // fall thro
  2709. case(F_MOVE2): // fall thro
  2710. case(F_MOVE): fprintf(stdout,"INFO: Transforming spectrum and writing output.\n");break;
  2711. case(F_SYLABTROF):
  2712. sprintf(errstr,"Should not be visited on this pass (%d).\n",passno);
  2713. return PROGRAM_ERROR;
  2714. default:
  2715. sprintf(errstr,"Unknown mode in pass %d.\n",passno);
  2716. return PROGRAM_ERROR;
  2717. }
  2718. break;
  2719. }
  2720. fflush(stdout);
  2721. /* TEST *
  2722. fprintf(stderr,"START of OUTER LOOP passno = %d\n",passno);
  2723. /* TEST */
  2724. sndseekEx(dz->ifd[0],0,0);
  2725. if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
  2726. return(exit_status);
  2727. dz->total_windows = 0;
  2728. dz->time = 0.0;
  2729. while(dz->ssampsread > 0) {
  2730. dz->flbufptr[0] = dz->bigfbuf;
  2731. windows_in_buf = dz->ssampsread/dz->wanted;
  2732. /* TEST *
  2733. fprintf(stderr,"GOING TO INNER LOOP passno = %d\n",passno);
  2734. /* TEST */
  2735. if((exit_status = new_inner_loop(windows_in_buf,&fmax,passno,limit,&inner_lpcnt,&phase,&times_index,&target,&previouspk,contourcnt,arp_param,&up,minpitch,maxpitch,dz))<0)
  2736. return(exit_status);
  2737. if(passno == FPROCESS) { // (pass 2)
  2738. switch(dz->mode) {
  2739. case(F_SEE): // Normalise pseudosndfile output
  2740. for(n = 0;n < dz->ssampsread;n++)
  2741. dz->bigfbuf[n] = (float)(dz->bigfbuf[n] * normaliser);
  2742. break;
  2743. case(F_SEEPKS): // Output is to textfile
  2744. case(F_SYLABTROF):
  2745. case(F_MAKEFILT):
  2746. break;
  2747. default: // Write analfile output
  2748. /* TEST *
  2749. fprintf(stderr,"WRITING OUTPUT\n");
  2750. /* TEST */
  2751. if((exit_status = write_samps(dz->bigfbuf,dz->ssampsread,dz))<0)
  2752. return(exit_status);
  2753. break;
  2754. }
  2755. }
  2756. if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
  2757. return(exit_status);
  2758. }
  2759. switch(passno) {
  2760. case(FPREANAL):
  2761. if(dz->mode != F_SYLABTROF) {
  2762. if((exit_status = tidy_up_pitch_data(dz))<0)
  2763. return(exit_status);
  2764. }
  2765. switch(dz->mode) {
  2766. case(F_PINVERT):// fall thro
  2767. case(F_PEXAGG):
  2768. if(dz->param[COLFLT] <= 0.0) { // No centre pivot, specified, use the mean
  2769. if((exit_status = getmeanpitch(&dz->param[COLFLT],&minpitch,&maxpitch,dz))<0)
  2770. return exit_status;
  2771. }
  2772. break;
  2773. case(F_PQUANT):
  2774. if((exit_status = pitch_quantise_all(dz))<0)
  2775. return exit_status;
  2776. break;
  2777. case(F_PCHRAND):
  2778. if(dz->quantcnt) {
  2779. if((exit_status = pitch_quantise_all(dz))<0)
  2780. return exit_status;
  2781. }
  2782. if((exit_status = pitch_randomise_all(dz))<0)
  2783. return exit_status;
  2784. break;
  2785. }
  2786. break;
  2787. case(FSPECENV): // (pass 1)
  2788. switch(dz->mode) {
  2789. case(F_SEE):
  2790. if(fmax < VERY_TINY_VAL) {
  2791. sprintf(errstr,"No significant data found in input file.\n");
  2792. return DATA_ERROR;
  2793. }
  2794. normaliser = SPECFNU_MAXLEVEL/fmax;
  2795. break;
  2796. case(F_SINUS):
  2797. if((exit_status = formants_smooth_and_quantise_all(dz))<0)
  2798. return exit_status;
  2799. break;
  2800. }
  2801. break;
  2802. case(FPROCESS): // (pass 2)
  2803. if(dz->mode == F_MAKEFILT) {
  2804. if((exit_status = build_filter(times_index,dz)) < 0)
  2805. return(exit_status);
  2806. }
  2807. break;
  2808. }
  2809. if(dz->ssampsread < 0) {
  2810. sprintf(errstr,"Sound read error.\n");
  2811. return(SYSTEM_ERROR);
  2812. }
  2813. /* TEST *
  2814. fprintf(stderr,"END of outer_loop passno = %d\n",passno);
  2815. /* TEST */
  2816. if(passno == 0 && dz->mode == F_SYLABTROF) {
  2817. if((exit_status = trof_detect(dz))<0)
  2818. return(exit_status);
  2819. break;
  2820. }
  2821. passno++;
  2822. }
  2823. if(dz->mode == F_SEE || dz->mode == F_SEEPKS || dz->mode == F_MAKEFILT || dz->mode == F_SYLABTROF)
  2824. return FINISHED;
  2825. if(!dz->ischange) {
  2826. sprintf(errstr,"NO CHANGE TO THE ORIGINAL SOUND\n");
  2827. return DATA_ERROR;
  2828. }
  2829. // Write final zero buffers to avoid any end click
  2830. dz->flbufptr[0] = dz->bigfbuf;
  2831. zerolen = dz->infile->Mlen/dz->infile->Dfac;
  2832. for(n=0;n<zerolen;n++) {
  2833. memset((char *)dz->flbufptr[0],0,(size_t)dz->wanted * sizeof(float));
  2834. thisfrq = 0.0;
  2835. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  2836. dz->flbufptr[0][FREQ] = (float)thisfrq;
  2837. thisfrq += dz->chwidth;
  2838. }
  2839. dz->flbufptr[0] += dz->wanted;
  2840. }
  2841. if((exit_status = write_samps(dz->bigfbuf,zerolen * dz->wanted,dz))<0)
  2842. return(exit_status);
  2843. return FINISHED;
  2844. }
  2845. /************************** SETUP_FORMANT_ARRAYS *********************/
  2846. int setup_formant_arrays(int *contourcnt,dataptr dz)
  2847. {
  2848. int exit_status, scalefact;
  2849. int arraycnt, contour_halfbands_per_step;
  2850. dz->specenv_type = FREQWISE_FORMANTS; // Frqwise formants seem to give more obvious formant peaks (pitvchwise is multipeaky)
  2851. scalefact = (int)round((double)dz->clength/(double)CLENGTH_DEFAULT);
  2852. dz->formant_bands *= scalefact; // Width of spectral-envelope bands depends on number of anal points actually used
  2853. if((exit_status = initialise_specenv(&arraycnt,dz))<0) // Formant arrays set up here
  2854. return(exit_status);
  2855. if((exit_status = set_the_specenv_frqs(arraycnt,dz))<0) // dz->specenvcnt (& dz->infile->specenvcnt) established here
  2856. return(exit_status); // (both required in formant library functions)
  2857. dz->descriptor_samps = dz->specenvcnt * DESCRIPTOR_DATA_BLOKS;
  2858. if(is_coloring(dz)) {
  2859. if((dz->specenvamp2 = (float *)malloc(dz->specenvcnt * sizeof(float)))==NULL) {
  2860. sprintf(errstr,"INSUFFICIENT MEMORY for second formant amplitude array.\n");
  2861. return(MEMORY_ERROR);
  2862. }
  2863. }
  2864. if(*contourcnt) {
  2865. contour_halfbands_per_step = SPECFNU_LONG_FBANDS * scalefact; // Width of spectral-contour bands depends on number of anal points actually used
  2866. if((exit_status = initialise_contourenv(contourcnt,contour_halfbands_per_step,dz))<0) // Contour arrays set up here
  2867. return(exit_status);
  2868. }
  2869. return(FINISHED);
  2870. }
  2871. /************************ SET_SPECENV_FRQS ************************
  2872. *
  2873. * FREQWISE BANDS = number of channels for each specenv point
  2874. */
  2875. int set_the_specenv_frqs(int arraycnt,dataptr dz)
  2876. {
  2877. double frqstep, thisfrq, nextfrq;
  2878. int k = 0;
  2879. dz->specenvamp[0] = (float)0.0;
  2880. dz->specenvfrq[0] = (float)1.0;
  2881. dz->specenvpch[0] = (float)log10(dz->specenvfrq[0]);
  2882. dz->specenvtop[0] = (float)dz->halfchwidth;
  2883. frqstep = dz->halfchwidth * (double)dz->formant_bands;
  2884. dz->frq_step = frqstep;
  2885. thisfrq = dz->specenvtop[0];
  2886. k = 1;
  2887. while((nextfrq = thisfrq + frqstep) < dz->nyquist) {
  2888. if(k >= arraycnt) {
  2889. sprintf(errstr,"Formant array too small: set_the_specenv_frqs()\n");
  2890. return(PROGRAM_ERROR);
  2891. }
  2892. dz->specenvfrq[k] = (float)nextfrq;
  2893. dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
  2894. dz->specenvtop[k] = (float)min(dz->nyquist,nextfrq);
  2895. thisfrq = nextfrq;
  2896. k++;
  2897. }
  2898. dz->specenvfrq[k] = (float)dz->nyquist;
  2899. dz->specenvpch[k] = (float)log10(dz->nyquist);
  2900. dz->specenvtop[k] = (float)dz->nyquist;
  2901. dz->specenvamp[k] = (float)0.0;
  2902. k++;
  2903. dz->specenvcnt = k;
  2904. dz->infile->specenvcnt = dz->specenvcnt;
  2905. return(FINISHED);
  2906. }
  2907. /**************************** NEW_INNER_LOOP ***************************/
  2908. int new_inner_loop(int windows_in_buf,double *fmax,int passno,int limit,int *inner_lpcnt,double *phase,int *times_index,
  2909. double *target,int *previouspk,int contourcnt,int arp_param,int *up,double minpitch, double maxpitch,dataptr dz)
  2910. {
  2911. int exit_status;
  2912. int wc;
  2913. double totalamp = 0.0;
  2914. for(wc=0; wc<windows_in_buf; wc++) {
  2915. /* TEST *
  2916. if(passno == 2)
  2917. fprintf(stderr,"wc = %d\n",wc);
  2918. /* TEST */
  2919. if(dz->total_windows==0) {
  2920. if(passno == FPREANAL && dz->mode != F_SYLABTROF)
  2921. dz->pitches[0] = (float)NOT_PITCH;
  2922. else
  2923. memset((char *)dz->flbufptr[0],0,(size_t)dz->wanted * sizeof(float));
  2924. } else {
  2925. if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
  2926. return(exit_status);
  2927. rectify_window(dz->flbufptr[0],dz);
  2928. switch(passno) {
  2929. case(FPREANAL): // (pass 0)
  2930. if((exit_status = get_totalamp(&totalamp,dz->flbufptr[0],dz->wanted))<0)
  2931. return(exit_status);
  2932. dz->parray[P_PRETOTAMP][dz->total_windows] = totalamp;
  2933. if(dz->mode != F_SYLABTROF) {
  2934. if((exit_status = specpitch(*inner_lpcnt,target,dz))<0)
  2935. return(exit_status);
  2936. }
  2937. break;
  2938. case(FSPECENV): // (pass 1)
  2939. if((exit_status = extract_specenv(0,0,dz))<0)
  2940. return(exit_status);
  2941. switch(dz->mode) {
  2942. case(F_NARROW): // fall thro
  2943. case(F_SQUEEZE): // fall thro
  2944. case(F_INVERT): // fall thro
  2945. case(F_ROTATE): // fall thro
  2946. case(F_SUPPRESS): // fall thro
  2947. case(F_MOVE): // fall thro
  2948. case(F_MOVE2): // fall thro
  2949. case(F_SINUS): // fall thro
  2950. case(F_MAKEFILT): exit_status = get_peaks_and_trofs(*inner_lpcnt,limit,previouspk,dz); break;
  2951. case(F_SEE): exit_status = get_fmax(fmax,dz); break;
  2952. case(F_ARPEG): // fall thro
  2953. case(F_OCTSHIFT): // fall thro
  2954. case(F_TRANS): // fall thro
  2955. case(F_FRQSHIFT): // fall thro
  2956. case(F_RESPACE): // fall thro
  2957. case(F_PINVERT): // fall thro
  2958. case(F_PEXAGG): // fall thro
  2959. case(F_PQUANT): // fall thro
  2960. case(F_PCHRAND): // fall thro
  2961. case(F_RAND): /* Spec colouring doesn't need peak and trof info */ break;
  2962. }
  2963. break;
  2964. case(FPROCESS): // (pass 2)
  2965. if((exit_status = extract_specenv(0,0,dz))<0)
  2966. return(exit_status);
  2967. switch(dz->mode) {
  2968. case(F_NARROW): exit_status = formants_narrow(*inner_lpcnt,dz); break;
  2969. case(F_SQUEEZE): exit_status = formants_squeeze(*inner_lpcnt,dz); break;
  2970. case(F_INVERT): exit_status = formants_invert(*inner_lpcnt,phase,contourcnt,dz); break;
  2971. case(F_ROTATE): exit_status = formants_rotate(*inner_lpcnt,phase,dz); break;
  2972. case(F_SUPPRESS):exit_status = formants_suppress(*inner_lpcnt,dz); break;
  2973. case(F_MOVE2): // fall thro
  2974. case(F_MOVE): exit_status = formants_move(*inner_lpcnt,dz); break;
  2975. case(F_MAKEFILT):exit_status = formants_makefilt(*inner_lpcnt,times_index,dz); break;
  2976. case(F_SEE): exit_status = formants_see(dz); break;
  2977. case(F_NEGATE): exit_status = formants_negate(contourcnt,dz); break;
  2978. case(F_SINUS): exit_status = formants_sinus(*inner_lpcnt,dz); break;
  2979. case(F_ARPEG): // fall thro
  2980. case(F_OCTSHIFT): // fall thro
  2981. case(F_TRANS): // fall thro
  2982. case(F_FRQSHIFT): // fall thro
  2983. case(F_RESPACE): // fall thro
  2984. case(F_PINVERT): // fall thro
  2985. case(F_PEXAGG): // fall thro
  2986. case(F_PQUANT): // fall thro
  2987. case(F_PCHRAND): // fall thro
  2988. case(F_RAND): exit_status = formants_recolor(*inner_lpcnt,phase,up,arp_param,minpitch,maxpitch,contourcnt,dz);break;
  2989. case(F_SEEPKS): exit_status = formants_seepks(dz); break;
  2990. }
  2991. break;
  2992. }
  2993. if(exit_status<0)
  2994. return(exit_status);
  2995. /* TEST *
  2996. fprintf(stderr,"END OF new_inner_loop passno = %d inner_lpcnt = %d of %d\n",passno,*inner_lpcnt,dz->wlength);
  2997. /* TEST */
  2998. }
  2999. dz->flbufptr[0] += dz->wanted;
  3000. dz->total_windows++;
  3001. dz->time = (float)(dz->time + dz->frametime);
  3002. (*inner_lpcnt)++;
  3003. }
  3004. return(FINISHED);
  3005. }
  3006. /************************** CHECK_SPECFNU_PARAM_VALIDITY_AND_CONSISTENCY *********************/
  3007. int check_specfnu_param_validity_and_consistency(dataptr dz)
  3008. {
  3009. int exit_status;
  3010. double brkmax = 0.0, brkmin = 0.0;
  3011. if(dz->mode == F_PCHRAND) {
  3012. if(dz->brksize[FPRMAXINT]) {
  3013. if((exit_status = get_maxvalue_in_brktable(&brkmax,FPRMAXINT,dz))<0)
  3014. return exit_status;
  3015. }
  3016. if(dz->param[FPRMAXINT] == 0.0) {
  3017. sprintf(errstr,"RANDOMISATION RANGE IS ZERO: THIS HAS NO EFFECT.\n");
  3018. return DATA_ERROR;
  3019. }
  3020. }
  3021. switch(dz->mode) {
  3022. case(F_SINUS):
  3023. if(dz->vflag[FSIN_FUND])
  3024. dz->fundamental = 1;
  3025. if(dz->vflag[FSIN_EXI])
  3026. dz->retain_unpitched_data_for_deletion = 1;
  3027. break;
  3028. case(F_ROTATE):
  3029. if(dz->brksize[RSPEED]) {
  3030. if((exit_status = get_maxvalue_in_brktable(&brkmax,RSPEED,dz))<0)
  3031. return exit_status;
  3032. }
  3033. if(dz->param[RSPEED] > (double)((int)floor(1.0/dz->frametime))) {
  3034. sprintf(errstr,"ROTATION RATE TOO HIGH FOR THIS ANALYSIS DATA.\n");
  3035. return DATA_ERROR;
  3036. }
  3037. if(dz->vflag[ROTATE_XNH] && dz->vflag[ROTATE_KHM]) {
  3038. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3039. return DATA_ERROR;
  3040. }
  3041. dz->fundamental = 1;
  3042. if(dz->vflag[ROTATE_EXI])
  3043. dz->retain_unpitched_data_for_deletion = 1;
  3044. break;
  3045. case(F_INVERT):
  3046. if(dz->brksize[FVIB]) {
  3047. if((exit_status = get_maxvalue_in_brktable(&brkmax,FVIB,dz))<0)
  3048. return exit_status;
  3049. }
  3050. if(dz->param[FVIB] > (double)((int)floor(1.0/dz->frametime))) {
  3051. sprintf(errstr,"VIBRATO RATE TOO HIGH FOR THIS ANALYSIS DATA.\n");
  3052. return DATA_ERROR;
  3053. }
  3054. if(dz->vflag[INVERT_XNH] && dz->vflag[INVERT_KHM]) {
  3055. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3056. return DATA_ERROR;
  3057. }
  3058. dz->fundamental = 1;
  3059. if(dz->vflag[INVERT_EXI])
  3060. dz->retain_unpitched_data_for_deletion = 1;
  3061. break;
  3062. case(F_PEXAGG): // fall thro
  3063. case(F_PINVERT):
  3064. if(dz->brksize[COLFLT]) {
  3065. if((exit_status = get_minvalue_in_brktable(&brkmin,COLFLT,dz))<0)
  3066. return exit_status;
  3067. if(dz->param[COLFLT] <= 0) {
  3068. sprintf(errstr,"Bottom of range is %d : Enter 0 only as flag (indicates \"use mean pitch of input\")\n",SPEC_MIDIMIN);
  3069. return DATA_ERROR;
  3070. }
  3071. }
  3072. // fall thro
  3073. case(F_PCHRAND): // fall thro
  3074. case(F_PQUANT):
  3075. if(dz->vflag[RECOLOR_DWN] || dz->vflag[RECOLOR_CYC]) {
  3076. if(!dz->brksize[COLRATE] && dz->param[COLRATE] == 0.0) {
  3077. if(dz->vflag[RECOLOR_DWN])
  3078. fprintf(stdout,"WARNING: Downward orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3079. if(dz->vflag[RECOLOR_CYC])
  3080. fprintf(stdout,"WARNING: Cyclic orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3081. fflush(stdout);
  3082. }
  3083. }
  3084. if(dz->vflag[RECOLOR_DWN] && dz->vflag[RECOLOR_CYC]) {
  3085. sprintf(errstr,"CANNOT ARPEGGIATE SPECTRUM BOTH \"DOWN\" AND \"CYCLICALLY\".\n");
  3086. return DATA_ERROR;
  3087. }
  3088. dz->fundamental = 1;
  3089. if(dz->vflag[RECOLOR_EXI])
  3090. dz->retain_unpitched_data_for_deletion = 1;
  3091. break;
  3092. case(F_ARPEG): // fall thro
  3093. case(F_OCTSHIFT): // fall thro
  3094. case(F_TRANS): // fall thro
  3095. case(F_FRQSHIFT): // fall thro
  3096. case(F_RESPACE): // fall thro
  3097. case(F_RAND):
  3098. if(dz->mode != F_ARPEG) {
  3099. if(dz->vflag[RECOLOR_DWN] || dz->vflag[RECOLOR_CYC]) {
  3100. if(!dz->brksize[COLRATE] && dz->param[COLRATE] == 0.0) {
  3101. if(dz->vflag[RECOLOR_DWN])
  3102. fprintf(stdout,"WARNING: Downward orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3103. if(dz->vflag[RECOLOR_CYC])
  3104. fprintf(stdout,"WARNING: Cyclic orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3105. fflush(stdout);
  3106. }
  3107. }
  3108. }
  3109. if(dz->vflag[RECOLOR_DWN] && dz->vflag[RECOLOR_CYC]) {
  3110. sprintf(errstr,"CANNOT ARPEGGIATE SPECTRUM BOTH \"DOWN\" AND \"CYCLICALLY\".\n");
  3111. return DATA_ERROR;
  3112. }
  3113. dz->fundamental = 1;
  3114. if(dz->vflag[RECOLOR_EXI])
  3115. dz->retain_unpitched_data_for_deletion = 1;
  3116. break;
  3117. case(F_SUPPRESS):
  3118. dz->suprflag = 0;
  3119. switch(dz->iparam[SUPRF]) { // Set flags for which formant to suppress
  3120. case(1): dz->suprflag |= 1; break;
  3121. case(2): dz->suprflag |= 2; break;
  3122. case(3): dz->suprflag |= 4; break;
  3123. case(4): dz->suprflag |= 8; break;
  3124. case(12): // fall thro
  3125. case(21): dz->suprflag |= 3; break;
  3126. case(13): // fall thro
  3127. case(31): dz->suprflag |= 5; break;
  3128. case(14): // fall thro
  3129. case(41): dz->suprflag |= 9; break;
  3130. case(23): // fall thro
  3131. case(32): dz->suprflag |= 6; break;
  3132. case(24): // fall thro
  3133. case(42): dz->suprflag |= 10; break;
  3134. case(34): // fall thro
  3135. case(43): dz->suprflag |= 12; break;
  3136. case(123): // fall thro
  3137. case(132): // fall thro
  3138. case(213): // fall thro
  3139. case(231): // fall thro
  3140. case(312): // fall thro
  3141. case(321): dz->suprflag |= 7; break;
  3142. case(124): // fall thro
  3143. case(142): // fall thro
  3144. case(214): // fall thro
  3145. case(241): // fall thro
  3146. case(412): // fall thro
  3147. case(421): dz->suprflag |= 11; break;
  3148. case(134): // fall thro
  3149. case(143): // fall thro
  3150. case(314): // fall thro
  3151. case(341): // fall thro
  3152. case(413): // fall thro
  3153. case(431): dz->suprflag |= 13; break;
  3154. case(234): // fall thro
  3155. case(243): // fall thro
  3156. case(324): // fall thro
  3157. case(342): // fall thro
  3158. case(423): // fall thro
  3159. case(432): dz->suprflag |= 14; break;
  3160. case(1234): // fall thro
  3161. case(1243): // fall thro
  3162. case(1324): // fall thro
  3163. case(1342): // fall thro
  3164. case(1423): // fall thro
  3165. case(1432): // fall thro
  3166. case(2134): // fall thro
  3167. case(2143): // fall thro
  3168. case(2314): // fall thro
  3169. case(2341): // fall thro
  3170. case(2413): // fall thro
  3171. case(2431): // fall thro
  3172. case(3124): // fall thro
  3173. case(3142): // fall thro
  3174. case(3214): // fall thro
  3175. case(3241): // fall thro
  3176. case(3412): // fall thro
  3177. case(3421): // fall thro
  3178. case(4123): // fall thro
  3179. case(4132): // fall thro
  3180. case(4213): // fall thro
  3181. case(4231): // fall thro
  3182. case(4312): // fall thro
  3183. case(4321): dz->suprflag |= 15; break;
  3184. default:
  3185. sprintf(errstr,"Suppress param must \"1\",\"2\",\"3\", or \"4\" or some combo of these, with no repeated items.\n");
  3186. return DATA_ERROR;
  3187. }
  3188. break;
  3189. case(F_NARROW):
  3190. dz->suprflag = 0;
  3191. switch(dz->iparam[NARSUPRES]) {
  3192. case(0): break;
  3193. case(1): dz->suprflag |= 1; break;
  3194. case(2): dz->suprflag |= 2; break;
  3195. case(3): dz->suprflag |= 4; break;
  3196. case(4): dz->suprflag |= 8; break;
  3197. case(12): // fall thro
  3198. case(21): dz->suprflag |= 3; break;
  3199. case(13): // fall thro
  3200. case(31): dz->suprflag |= 5; break;
  3201. case(14): // fall thro
  3202. case(41): dz->suprflag |= 9; break;
  3203. case(23): // fall thro
  3204. case(32): dz->suprflag |= 6; break;
  3205. case(24): // fall thro
  3206. case(42): dz->suprflag |= 10; break;
  3207. case(34): // fall thro
  3208. case(43): dz->suprflag |= 12; break;
  3209. case(123): // fall thro
  3210. case(132): // fall thro
  3211. case(213): // fall thro
  3212. case(231): // fall thro
  3213. case(312): // fall thro
  3214. case(321): dz->suprflag |= 7; break;
  3215. case(124): // fall thro
  3216. case(142): // fall thro
  3217. case(214): // fall thro
  3218. case(241): // fall thro
  3219. case(412): // fall thro
  3220. case(421): dz->suprflag |= 11; break;
  3221. case(134): // fall thro
  3222. case(143): // fall thro
  3223. case(314): // fall thro
  3224. case(341): // fall thro
  3225. case(413): // fall thro
  3226. case(431): dz->suprflag |= 13; break;
  3227. case(234): // fall thro
  3228. case(243): // fall thro
  3229. case(324): // fall thro
  3230. case(342): // fall thro
  3231. case(423): // fall thro
  3232. case(432): dz->suprflag |= 14; break;
  3233. default:
  3234. sprintf(errstr,"Suppress param must \"1\",\"2\",\"3\", or \"4\" or some combo of 3 of these, with no repeated items.\n");
  3235. return DATA_ERROR;
  3236. }
  3237. dz->fundamental = 0;
  3238. if(dz->vflag[NRW_FUND]) {
  3239. if(dz->suprflag & 1) {
  3240. fprintf(stdout,"WARNING: Cannot \"Track Fundamental\" if supressing formants 1: Ignoring.\n");
  3241. fflush(stdout);
  3242. } else
  3243. dz->fundamental = 1;
  3244. }
  3245. if(dz->vflag[NRW_XNH] && dz->vflag[NRW_KHM]) {
  3246. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3247. return DATA_ERROR;
  3248. }
  3249. dz->fundamental = 1;
  3250. if(dz->vflag[NRW_EXI])
  3251. dz->retain_unpitched_data_for_deletion = 1;
  3252. break;
  3253. case(F_MAKEFILT):
  3254. if(dz->vflag[KEEPAMP] && dz->vflag[KEEPINV]) {
  3255. sprintf(errstr,"You cannot use both the peak amplitudes and the peak-amplitude-inverses.\n");
  3256. return DATA_ERROR;
  3257. }
  3258. dz->fundamental = 0;
  3259. if(dz->vflag[FLT_FUND])
  3260. dz->fundamental = 1;
  3261. break;
  3262. case(F_SQUEEZE):
  3263. dz->fundamental = 0;
  3264. if(dz->vflag[SQZ_FUND]) {
  3265. if(dz->vflag[AT_TROFS]) {
  3266. fprintf(stdout,"WARNING: Cannot \"Track Fundamental\" if squeezing around troughs: Ignoring.\n");
  3267. fflush(stdout);
  3268. } else if(dz->iparam[SQZAT] > 1) {
  3269. fprintf(stdout,"WARNING: Cannot \"Track Fundamental\" if not squeezing around 1st formant: Ignoring.\n");
  3270. fflush(stdout);
  3271. } else
  3272. dz->fundamental = 1;
  3273. }
  3274. if(dz->vflag[SQZ_XNH] && dz->vflag[SQZ_KHM]) {
  3275. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3276. return DATA_ERROR;
  3277. }
  3278. dz->fundamental = 1;
  3279. if(dz->vflag[SQZ_EXI])
  3280. dz->retain_unpitched_data_for_deletion = 1;
  3281. break;
  3282. case(F_NEGATE):
  3283. if(dz->vflag[NEG_XNH] && dz->vflag[NEG_KHM]) {
  3284. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3285. return DATA_ERROR;
  3286. }
  3287. if(dz->vflag[NEG_XNH] || dz->vflag[NEG_KHM])
  3288. dz->fundamental = 1;
  3289. if(dz->vflag[NEG_EXI])
  3290. dz->retain_unpitched_data_for_deletion = 1;
  3291. break;
  3292. case(F_MOVE):
  3293. if(dz->vflag[MOV_XNH] && dz->vflag[MOV_KHM]) {
  3294. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3295. return DATA_ERROR;
  3296. }
  3297. dz->fundamental = 1;
  3298. if(dz->vflag[MOV_EXI])
  3299. dz->retain_unpitched_data_for_deletion = 1;
  3300. break;
  3301. case(F_MOVE2):
  3302. if(dz->vflag[MOV2_XNH] && dz->vflag[MOV2_KHM]) {
  3303. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3304. return DATA_ERROR;
  3305. }
  3306. dz->fundamental = 1;
  3307. if(dz->vflag[MOV2_EXI])
  3308. dz->retain_unpitched_data_for_deletion = 1;
  3309. break;
  3310. }
  3311. if(dz->fundamental)
  3312. dz->needpitch = 1;
  3313. switch(dz->mode) {
  3314. case(F_OCTSHIFT):// fall thro
  3315. case(F_TRANS): // fall thro
  3316. case(F_FRQSHIFT):// fall thro
  3317. case(F_RESPACE): // fall thro
  3318. case(F_PINVERT): // fall thro
  3319. case(F_PEXAGG): // fall thro
  3320. case(F_PQUANT): // fall thro
  3321. case(F_PCHRAND): // fall thro
  3322. case(F_RAND):
  3323. if(dz->param[COL_LO] >= dz->param[COL_HI]) {
  3324. sprintf(errstr,"Low frq cutoff is >= high frq cutoff. No output will be generated.\n");
  3325. return DATA_ERROR;
  3326. }
  3327. break;
  3328. }
  3329. switch(dz->mode) {
  3330. case(F_PINVERT): // fall thro
  3331. case(F_PEXAGG): // fall thro
  3332. case(F_PQUANT): // fall thro
  3333. case(F_PCHRAND):
  3334. if(dz->param[COLLOPCH] >= dz->param[COLHIPCH]) {
  3335. sprintf(errstr,"Minimum acceptable pitch >= Maximum acceptable pitch. No output will be generated.\n");
  3336. return DATA_ERROR;
  3337. }
  3338. break;
  3339. }
  3340. return FINISHED;
  3341. }
  3342. /************************** FORMANTS_NARROW *********************/
  3343. int formants_narrow(int inner_lpcnt,dataptr dz)
  3344. {
  3345. int exit_status, n, k, thistrof, thispeak, nexttrof, spstt, spend, ccstt, vcstt, ccend = 0, ccendmax, vcend, cc, vc, chdiff, nuchdiff, chomit;
  3346. int zccstt, zccend, zvcstt, newcc, get_fundamental = 0, last_formant_zeroed, top_hno;
  3347. float frqstt, frqend, frq;
  3348. float newfrq, the_fundamental = 0.0;
  3349. double minamp, maxamp, constrict, pre_amptotal = 0.0, post_amptotal = 0.0;
  3350. int flbuf_pktrofs[9];
  3351. int *peakat = dz->iparray[PEAKPOS];
  3352. peakat += inner_lpcnt * PKBLOK;
  3353. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3354. return(exit_status);
  3355. if(dz->fundamental)
  3356. the_fundamental = dz->pitches[inner_lpcnt];
  3357. // FIND THE flbufptr LOCATIONS OF THE PEAKS AND TROFS INDICATED IN THE specevamp ENVELOPE CURVE
  3358. for(n = 0; n < PKBLOK; n+=2) { // Going through the trof and peaks in pairs
  3359. if(dz->fundamental && n == 0)
  3360. get_fundamental = 1;
  3361. thistrof = n;
  3362. thispeak = n+1;
  3363. nexttrof = n+2;
  3364. spstt = peakat[n]; // Get specenvamp locations of a trof.
  3365. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3366. frqstt = 0.0f;
  3367. else
  3368. frqstt = dz->specenvtop[spstt-1];
  3369. frqend = dz->specenvtop[spstt];
  3370. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3371. ccend = (int)ceil(frqend/dz->chwidth);
  3372. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3373. vcstt = ccstt * 2;
  3374. flbuf_pktrofs[thistrof] = ccstt;
  3375. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3376. if(dz->flbufptr[0][AMPP] < minamp) {
  3377. minamp = dz->flbufptr[0][AMPP];
  3378. flbuf_pktrofs[thistrof] = cc;
  3379. }
  3380. }
  3381. zccstt = flbuf_pktrofs[thistrof]; // Remember flbufptr location of trof, for use (if ness) in formant zeroing
  3382. if(n == PKBLOK - 1) // EXIT when final trof sussed.
  3383. break;
  3384. spend = peakat[nexttrof]; // Find specenv location of next TROF
  3385. frqstt = dz->specenvtop[spstt]; // Find the top of the frequency band associated with the lower trof
  3386. frqend = dz->specenvtop[spend - 1]; // Find the bottom of the frequency band associated with the upper trof
  3387. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3388. ccend = (int)ceil(frqend/dz->chwidth);
  3389. maxamp = -HUGE; // Find flbufptr location of PEAK amplitude between the trofs
  3390. vcstt = ccstt * 2;
  3391. flbuf_pktrofs[thispeak] = ccstt;
  3392. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3393. if(dz->flbufptr[0][AMPP] > maxamp) {
  3394. maxamp = dz->flbufptr[0][AMPP];
  3395. flbuf_pktrofs[thispeak] = cc;
  3396. }
  3397. }
  3398. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  3399. if(the_fundamental > 0.0) {
  3400. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  3401. return exit_status;
  3402. flbuf_pktrofs[thispeak] = newcc;
  3403. }
  3404. get_fundamental = 0; // Only (try to) get fundamental when in first formant
  3405. }
  3406. if(dz->suprflag) {
  3407. k = n/2;
  3408. k = (int)round(pow(2,k)); // n = 0,2,4,6 n/2 = 0,1,2,3 pow(2,n/2) = 1,2,4,8 = 0001,0010,0100,1000
  3409. if(dz->suprflag & k) { // If formant flagged for zeroing
  3410. spend = peakat[nexttrof]; // Find flbufptr location of minamp at NEXT trof
  3411. frqstt = dz->specenvtop[spend-1];
  3412. frqend = dz->specenvtop[spend];
  3413. ccstt = (int)ceil(frqstt/dz->chwidth);
  3414. ccend = (int)ceil(frqend/dz->chwidth);
  3415. minamp = HUGE;
  3416. zccend = ccstt;
  3417. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3418. if(dz->flbufptr[0][AMPP] < minamp) {
  3419. minamp = dz->flbufptr[0][AMPP];
  3420. zccend = cc;
  3421. }
  3422. }
  3423. zvcstt = zccstt * 2; // Zero flbufptr between the 2 trofs
  3424. for(cc = zccstt,vc = zvcstt; cc < zccend; cc++,vc+=2)
  3425. dz->flbufptr[0][AMPP] = 0.0f;
  3426. }
  3427. }
  3428. }
  3429. if(flbuf_pktrofs[0] > 0) { // zero spectrum below initial trof.
  3430. for(cc = 0,vc = 0; cc < flbuf_pktrofs[0]; cc++,vc+=2)
  3431. dz->flbufptr[0][AMPP] = 0.0f;
  3432. }
  3433. ccendmax = 0;
  3434. last_formant_zeroed = 0;
  3435. for(n = 0; n < PKBLOK-1; n++) { // Going through the trof and peaks in pairs
  3436. ccstt = flbuf_pktrofs[n]; // Find flbhfptr trof/peak.
  3437. ccend = flbuf_pktrofs[n+1]; // Find following flbufptr peak/trof.
  3438. if(n == PKBLOK-2)
  3439. ccendmax = ccend;
  3440. if(last_formant_zeroed)
  3441. break;
  3442. chdiff = ccend - ccstt; // Find channel step.
  3443. if(dz->suprflag) {
  3444. if(EVEN(n)) {
  3445. k = n/2;
  3446. k = (int)round(pow(2,k));
  3447. if(dz->suprflag & k) { // If formant zeroed
  3448. if(k == F4_ZEROED) // If last formant zeroed
  3449. last_formant_zeroed = 1; // Don't skip to next trof here as we want to set ccendmax before exiting!!!
  3450. else // but otherwise
  3451. n++; // skip to next trof
  3452. continue;
  3453. }
  3454. }
  3455. }
  3456. nuchdiff = (int)round((double)chdiff * dz->param[NARROWING]);
  3457. chomit = chdiff - nuchdiff; // Reduce it by SQUEEZE and see if any channels are lost
  3458. if(chomit > 0) {
  3459. k = 0; // If they are, zero this number of channels from trof, widening the trof.
  3460. if(EVEN(n)) { // If we're at a trof BEFORE a peak
  3461. while(k < chomit) { // forwardwise
  3462. vc = ccstt * 2;
  3463. dz->flbufptr[0][AMPP] = 0.0f;
  3464. k++;
  3465. ccstt++;
  3466. } // (and forcing trof start to zero).
  3467. } else { // If we're at a trof AFTER a peak
  3468. while(k < chomit) { // backwardswise
  3469. vc = ccend * 2;
  3470. dz->flbufptr[0][AMPP] = 0.0f;
  3471. k++;
  3472. ccend--;
  3473. }
  3474. }
  3475. }
  3476. chdiff = ccend - ccstt; // After possible expansion of trof, calculate new chdiff
  3477. vcstt = ccstt * 2;
  3478. vcend = ccend * 2;
  3479. if(EVEN(n)) { // Trof followed by peak, "splice" upwards: trof (possibly at new location) forced to zero: peak unchanged.
  3480. for(k = 0, cc = ccstt, vc = vcstt; cc < ccend; k++, cc++, vc+=2) {
  3481. constrict = (double)k/(double)chdiff;
  3482. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * constrict);
  3483. }
  3484. } else { // Peak followed by trof, "splice" downwards: trof (possibly at new location) forced to zero: peak unchanged.
  3485. for(k = 0, cc = ccend, vc = vcend; cc > ccstt; k++, cc--, vc-=2) {
  3486. constrict = (double)k/(double)chdiff;
  3487. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * constrict);
  3488. }
  3489. }
  3490. }
  3491. if(dz->vflag[ZEROTOP]) // Zero the remaining upper part of the spectrum (if flagged).
  3492. zero_spectrum_top(ccendmax,dz);
  3493. top_hno = 0;
  3494. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  3495. frq = dz->flbufptr[0][FREQ];
  3496. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3497. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3498. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3499. continue; // zero it
  3500. }
  3501. } else if(dz->vflag[NRW_KHM]) { // If suppressing harmonics
  3502. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3503. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3504. dz->flbufptr[0][AMPP] = 0.0f;
  3505. continue;
  3506. }
  3507. }
  3508. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3509. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3510. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3511. continue;
  3512. }
  3513. }
  3514. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3515. return(exit_status);
  3516. if(post_amptotal > pre_amptotal) {
  3517. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3518. return(exit_status);
  3519. }
  3520. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3521. for(vc=0;vc<dz->wanted;vc+=2)
  3522. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3523. }
  3524. return FINISHED;
  3525. }
  3526. /************************** FORMANTS_SQUEEZE *********************/
  3527. int formants_squeeze(int inner_lpcnt,dataptr dz)
  3528. {
  3529. int exit_status, thistrof, nexttrof, centre, spstt, spend, ccstt, vcstt, ccend, cc, vc, lastcc, locc, hicc, nucc, nuvc, newcc, top_hno, get_fundamental = 0;
  3530. float frqstt, frqend, frq, centrefrq, newfrq, the_fundamental = 0.0;
  3531. double lastamp, minamp, maxamp, frqoffset, nuoffset, nufrq, pre_amptotal = 0.0, post_amptotal = 0.0;
  3532. int *peakat = dz->iparray[PEAKPOS];
  3533. peakat += inner_lpcnt * PKBLOK;
  3534. if(dz->fundamental) {
  3535. get_fundamental = 1;
  3536. the_fundamental = dz->pitches[inner_lpcnt];
  3537. }
  3538. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3539. return(exit_status);
  3540. centre = (dz->iparam[SQZAT] * 2) - 1; // Formants 1,2,3,4 peaks at peaktrof-points 1,3,5,7
  3541. if(dz->vflag[AT_TROFS])
  3542. centre++; // Trofs above them at peaktrof-points 2,4,6,8
  3543. if(dz->vflag[AT_TROFS]) {
  3544. thistrof = centre;
  3545. spstt = peakat[thistrof]; // Get specenvamp locations of a trof.
  3546. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3547. frqstt = 0.0f;
  3548. else
  3549. frqstt = dz->specenvtop[spstt-1];
  3550. frqend = dz->specenvtop[spstt];
  3551. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3552. ccend = (int)ceil(frqend/dz->chwidth);
  3553. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3554. vcstt = ccstt * 2;
  3555. centre = ccstt;
  3556. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3557. if(dz->flbufptr[0][AMPP] < minamp) {
  3558. minamp = dz->flbufptr[0][AMPP];
  3559. centre = cc;
  3560. }
  3561. }
  3562. } else {
  3563. thistrof = centre - 1;
  3564. nexttrof = centre + 1;
  3565. spstt = peakat[thistrof]; // Find specenv location of previous TROF
  3566. spend = peakat[nexttrof]; // Find specenv location of next TROF
  3567. frqstt = dz->specenvtop[spstt]; // Find the top of the frequency band associated with the lower trof
  3568. frqend = dz->specenvtop[spend - 1]; // Find the bottom of the frequency band associated with the upper trof
  3569. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3570. ccend = (int)ceil(frqend/dz->chwidth);
  3571. maxamp = -HUGE; // Find flbufptr location of PEAK amplitude between the trofs
  3572. vcstt = ccstt * 2;
  3573. centre = ccstt;
  3574. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3575. if(dz->flbufptr[0][AMPP] > maxamp) {
  3576. maxamp = dz->flbufptr[0][AMPP];
  3577. centre = cc;
  3578. }
  3579. }
  3580. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  3581. if(the_fundamental > 0.0) {
  3582. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  3583. return exit_status;
  3584. centre = newcc;
  3585. }
  3586. get_fundamental = 0;
  3587. }
  3588. }
  3589. if(dz->xclude_nonh || dz->vflag[SQZ_KHM]) {
  3590. top_hno = 0;
  3591. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  3592. frq = dz->flbufptr[0][FREQ];
  3593. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3594. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3595. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3596. continue; // zero it
  3597. }
  3598. } else if(dz->vflag[SQZ_KHM]) { // If suppressing harmonics
  3599. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3600. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3601. dz->flbufptr[0][AMPP] = 0.0f;
  3602. continue;
  3603. }
  3604. }
  3605. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3606. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3607. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3608. continue;
  3609. }
  3610. }
  3611. }
  3612. vc = centre*2;
  3613. centrefrq = dz->flbufptr[0][FREQ]; // Note the freq at the centre of the shribkage
  3614. lastcc = -1; // Preset variables
  3615. lastamp = -HUGE;
  3616. locc = dz->clength + 1;
  3617. for(cc=0,vc=0;cc<centre;cc++,vc+=2) { // Squeezespectrum below centrefrq
  3618. frqoffset = centrefrq - dz->flbufptr[0][FREQ];
  3619. nuoffset = frqoffset * dz->param[SQZFACT]; // Find the altered frq of this channel, once spectrum squeezed
  3620. nufrq = centrefrq - nuoffset;
  3621. nucc = (int)round(nufrq/dz->chwidth); // Find new channel-location for this frq
  3622. if(nucc < locc)
  3623. locc = nucc; // Note the lowest channel used by squeezed spectrum
  3624. nuvc = nucc * 2;
  3625. if(nucc == lastcc) { // If some other data has already been moved into this channel, keep whichever is the loudest
  3626. if(dz->flbufptr[0][AMPP] > lastamp) {
  3627. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3628. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3629. }
  3630. } else { // Otherwise, simply move transformed data into this new channel (which may be original chan, just with a frq change)
  3631. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3632. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3633. }
  3634. lastamp = dz->flbufptr[0][nuvc];
  3635. lastcc = nucc;
  3636. }
  3637. for(cc=0,vc=0;cc<locc;cc++,vc+=2) // Zero spectrum below squeezed material.
  3638. dz->flbufptr[0][AMPP] = 0.0f;
  3639. cc = centre + 1; // Similar procedure for spectrum above centre
  3640. vc = cc * 2;
  3641. lastcc = -1;
  3642. lastamp = -HUGE;
  3643. hicc = -1;
  3644. for(;cc<dz->clength;cc++,vc+=2) {
  3645. frqoffset = dz->flbufptr[0][FREQ] - centrefrq;
  3646. nuoffset = frqoffset * dz->param[SQZFACT];
  3647. nufrq = centrefrq + nuoffset;
  3648. nucc = (int)round(nufrq/dz->chwidth);
  3649. if(nucc > hicc)
  3650. hicc = nucc; // But new locate the highest channel used by squeezed spectrum
  3651. nuvc = nucc * 2;
  3652. if(nucc == lastcc) {
  3653. if(dz->flbufptr[0][AMPP] > lastamp) {
  3654. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3655. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3656. }
  3657. } else {
  3658. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3659. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3660. }
  3661. lastamp = dz->flbufptr[0][nuvc];
  3662. lastcc = nucc;
  3663. }
  3664. cc = hicc + 1;
  3665. vc = cc * 2;
  3666. for(;cc<dz->clength;cc++,vc+=2) // Zero spectrum above squeezed material.
  3667. dz->flbufptr[0][AMPP] = 0.0f;
  3668. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3669. return(exit_status);
  3670. if(post_amptotal > pre_amptotal) {
  3671. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3672. return(exit_status);
  3673. }
  3674. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3675. for(vc=0;vc<dz->wanted;vc+=2)
  3676. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3677. }
  3678. return FINISHED;
  3679. }
  3680. /************************** FORMANTS_INVERT *********************/
  3681. int formants_invert(int inner_lpcnt,double *phase,int contourcnt,dataptr dz)
  3682. {
  3683. int exit_status, cc, vc, top_hno;
  3684. float the_fundamental;
  3685. double vibpos, frq, specamp, contouramp, diff, pre_amptotal = 0.0, post_amptotal = 0.0;
  3686. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3687. return(exit_status);
  3688. if((exit_status = extract_contour(contourcnt,dz))<0)
  3689. return exit_status;
  3690. top_hno = 0;
  3691. if(dz->xclude_nonh && dz->pitches[inner_lpcnt] < FSPEC_MINFRQ) {
  3692. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2)
  3693. dz->flbufptr[0][AMPP] = 0.0f;
  3694. } else {
  3695. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  3696. frq = (double)dz->flbufptr[0][FREQ];
  3697. the_fundamental = (float)dz->pitches[inner_lpcnt];
  3698. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3699. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,(float)frq,cc,&top_hno,dz)) {
  3700. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3701. continue; // zero it
  3702. }
  3703. } else if(dz->vflag[INVERT_KHM]) { // If suppressing harmonics
  3704. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3705. if(channel_holds_harmonic(the_fundamental,(float)frq,cc,&top_hno,dz)) {
  3706. dz->flbufptr[0][AMPP] = 0.0f;
  3707. continue;
  3708. }
  3709. }
  3710. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3711. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3712. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3713. continue;
  3714. }
  3715. if((exit_status = getspecenvamp(&specamp,frq,0,dz))<0) // Otherwise do spectral inversion
  3716. return(exit_status);
  3717. if((exit_status = getcontouramp(&contouramp,contourcnt,frq,dz))<0)
  3718. return(exit_status);
  3719. diff = specamp - contouramp;
  3720. if(dz->param[FVIB] != 0.0) {
  3721. vibpos = (sin(*phase)); // sin from -1to1
  3722. diff *= vibpos;
  3723. *phase = fmod(*phase + (dz->param[FVIB] * dz->phasefactor),TWOPI);
  3724. } // phase advance depends on current frq ; fmoded to stay within range 0 to 2PI
  3725. dz->flbufptr[0][AMPP] = (float)(max(0.0,contouramp - diff));
  3726. }
  3727. }
  3728. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3729. return(exit_status);
  3730. if(post_amptotal > pre_amptotal) {
  3731. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3732. return(exit_status);
  3733. }
  3734. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3735. for(vc=0;vc<dz->wanted;vc+=2)
  3736. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3737. }
  3738. return FINISHED;
  3739. }
  3740. /************************** FORMANTS_ROTATE *********************/
  3741. int formants_rotate(int inner_lpcnt,double *phase,dataptr dz)
  3742. {
  3743. int exit_status, spstt, spend, ccstt, ccend, vcstt, locc, lovc, hicc, hivc, cc, vc, nucc, nuvc, lastcc, top_hno;
  3744. float frqstt, frqend, lofrq, hifrq, frq, the_fundamental = 0.0;
  3745. double minamp, lastamp, frqdiff, frqstep, nufrq, phasestep, pre_amptotal = 0.0, post_amptotal = 0.0;
  3746. int *peakat = dz->iparray[PEAKPOS];
  3747. peakat += inner_lpcnt * PKBLOK;
  3748. if(dz->fundamental)
  3749. the_fundamental = dz->pitches[inner_lpcnt];
  3750. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3751. return(exit_status);
  3752. spstt = peakat[0];
  3753. spend = peakat[PKBLOK-1];
  3754. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3755. frqstt = 0.0f;
  3756. else
  3757. frqstt = dz->specenvtop[spstt-1];
  3758. frqend = dz->specenvtop[spstt];
  3759. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3760. ccend = (int)ceil(frqend/dz->chwidth);
  3761. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3762. vcstt = ccstt * 2;
  3763. locc = ccstt;
  3764. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3765. if(dz->flbufptr[0][AMPP] < minamp) {
  3766. minamp = dz->flbufptr[0][AMPP];
  3767. locc = cc;
  3768. }
  3769. }
  3770. lovc = locc * 2;
  3771. vc = lovc;
  3772. lofrq = dz->flbufptr[0][FREQ];
  3773. frqstt = dz->specenvtop[spend-1];
  3774. frqend = dz->specenvtop[spend];
  3775. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3776. ccend = (int)ceil(frqend/dz->chwidth);
  3777. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3778. vcstt = ccstt * 2;
  3779. hicc = ccstt;
  3780. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3781. if(dz->flbufptr[0][AMPP] < minamp) {
  3782. minamp = dz->flbufptr[0][AMPP];
  3783. hicc = cc;
  3784. }
  3785. }
  3786. hivc = hicc * 2;
  3787. vc = hivc;
  3788. hifrq = dz->flbufptr[0][FREQ];
  3789. frqdiff = hifrq - lofrq;
  3790. frqstep = (*phase) * frqdiff;
  3791. lastcc = -1;
  3792. lastamp = -HUGE;
  3793. if(dz->xclude_nonh || dz->vflag[ROTATE_KHM]) {
  3794. top_hno = 0;
  3795. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  3796. frq = dz->flbufptr[0][FREQ];
  3797. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3798. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3799. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3800. continue; // zero it
  3801. }
  3802. } else if(dz->vflag[ROTATE_KHM]) { // If suppressing harmonics
  3803. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3804. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3805. dz->flbufptr[0][AMPP] = 0.0f;
  3806. continue;
  3807. }
  3808. }
  3809. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3810. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3811. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3812. continue;
  3813. }
  3814. }
  3815. }
  3816. for(cc = locc, vc = lovc; cc <= hivc; cc++, vc+=2) {
  3817. nufrq = dz->flbufptr[0][FREQ] + frqstep;
  3818. while(nufrq > hifrq) // Keep nufrq within bounds
  3819. nufrq -= frqdiff;
  3820. while(nufrq < lofrq)
  3821. nufrq += frqdiff;
  3822. nucc = (int)round(nufrq/dz->chwidth); // Find new channel-location for this frq
  3823. nuvc = nucc * 2;
  3824. if(nucc == lastcc) { // If some other data has already been moved into this channel, keep whichever is the loudest
  3825. if(dz->flbufptr[0][AMPP] > lastamp) {
  3826. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3827. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3828. }
  3829. } else { // Otherwise, simply move transformed data into this new channel (which may be original chan, just with a frq change)
  3830. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3831. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3832. }
  3833. lastamp = dz->flbufptr[0][nuvc];
  3834. lastcc = nucc;
  3835. }
  3836. phasestep = dz->phasefactor * dz->param[RSPEED];
  3837. *phase += phasestep; // Advance phase according to rotation-speed.
  3838. while(*phase > 1.0) // Keep rotation "phase" within 0-1 bounds.
  3839. *phase -= 1.0;
  3840. while(*phase < 0.0)
  3841. *phase += 1.0;
  3842. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3843. return(exit_status);
  3844. if(post_amptotal > pre_amptotal) {
  3845. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3846. return(exit_status);
  3847. }
  3848. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3849. for(vc=0;vc<dz->wanted;vc+=2)
  3850. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3851. }
  3852. return FINISHED;
  3853. }
  3854. /************************** FORMANTS_SUPPRESS *********************/
  3855. int formants_suppress(int inner_lpcnt,dataptr dz)
  3856. {
  3857. int exit_status, n, k, pk, thistrof, nexttrof, spstt, spend, ccstt, vcstt, ccend, pretrof, posttrof, cc ,vc, chandiff;
  3858. float frqstt, frqend;
  3859. double ampdiff, amphere, thisvalue, preminamp, postminamp, thisspecamp, pre_amptotal = 0.0, post_amptotal = 0.0;
  3860. int *peakat = dz->iparray[PEAKPOS];
  3861. peakat += inner_lpcnt * PKBLOK;
  3862. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3863. return(exit_status);
  3864. for(n = 0,pk = 1; n < PKBLOK-1; n+=2,pk *=2) { // Going through the trofs in pairs
  3865. if(dz->suprflag & pk) { // If this formant is to be supressed
  3866. thistrof = n;
  3867. nexttrof = n+2;
  3868. spstt = peakat[thistrof]; // Get specenvamp locations of a trof.
  3869. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3870. frqstt = 0.0f;
  3871. else
  3872. frqstt = dz->specenvtop[spstt-1];
  3873. frqend = dz->specenvtop[spstt];
  3874. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3875. ccend = (int)ceil(frqend/dz->chwidth);
  3876. preminamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3877. vcstt = ccstt * 2;
  3878. pretrof = ccstt;
  3879. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3880. if(dz->flbufptr[0][AMPP] < preminamp) {
  3881. preminamp = dz->flbufptr[0][AMPP];
  3882. pretrof = cc;
  3883. }
  3884. }
  3885. spend = peakat[nexttrof]; // Get specenvamp locations of next trof.
  3886. frqstt = dz->specenvtop[spend-1];
  3887. frqend = dz->specenvtop[spend];
  3888. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3889. ccend = (int)ceil(frqend/dz->chwidth);
  3890. postminamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3891. vcstt = ccstt * 2;
  3892. posttrof = ccstt;
  3893. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3894. if(dz->flbufptr[0][AMPP] < postminamp) {
  3895. postminamp = dz->flbufptr[0][AMPP];
  3896. posttrof = cc;
  3897. }
  3898. }
  3899. ampdiff = postminamp - preminamp;
  3900. chandiff = posttrof - pretrof;
  3901. cc = pretrof + 1; // Scale the intervening channel amps to a linear interp between the 2 trofs
  3902. vc = cc * 2;
  3903. k = 1;
  3904. for(k = 1;k < chandiff;k++,cc++,vc+=2) {
  3905. amphere = ampdiff * ((double)k/(double)chandiff);
  3906. if((exit_status = getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
  3907. return(exit_status);
  3908. if(thisspecamp <= 0.0)
  3909. dz->flbufptr[0][AMPP] = 0.0f;
  3910. else {
  3911. if((thisvalue = dz->flbufptr[0][AMPP] * amphere/thisspecamp) < VERY_TINY_VAL)
  3912. dz->flbufptr[0][AMPP] = 0.0f;
  3913. else
  3914. dz->flbufptr[0][AMPP] = (float)thisvalue;
  3915. }
  3916. }
  3917. }
  3918. }
  3919. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3920. return(exit_status);
  3921. if(post_amptotal > pre_amptotal) {
  3922. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3923. return(exit_status);
  3924. }
  3925. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3926. for(vc=0;vc<dz->wanted;vc+=2)
  3927. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3928. }
  3929. return FINISHED;
  3930. }
  3931. /********************* FORMANTS_SEE *************************/
  3932. int formants_see(dataptr dz)
  3933. {
  3934. int cc,vc, k, blokcnt = SPECFNU_BLOKCNT;
  3935. double thisamp;
  3936. if(dz->specenvcnt * blokcnt >= dz->wanted) {
  3937. sprintf(errstr,"Writing output will overrun buffer.\n");
  3938. return PROGRAM_ERROR;
  3939. }
  3940. blokcnt = 7;
  3941. for(cc=0,vc=0;cc<dz->specenvcnt;cc++,vc+=blokcnt) {
  3942. thisamp = dz->specenvamp[cc];
  3943. for(k=0;k<blokcnt;k++)
  3944. dz->flbufptr[0][vc+k] = (float)thisamp; // Write amplitude vals sequentially, in blocks of 7, for easy viewability
  3945. }
  3946. while(vc<dz->wanted) // Fill up rest of output block with zeros
  3947. dz->flbufptr[0][vc++] = 0.0f;
  3948. return(FINISHED);
  3949. }
  3950. /********************* FORMANTS_SEE *************************/
  3951. int formants_seepks(dataptr dz)
  3952. {
  3953. int n, k, pad, trofcnt = 0, peakcnt = 0, rising = 0, done = 0, vc = 0, localmaxat = 0, localminat = 0;
  3954. double lastamp, thismaxamp = 0.0, thisminamp = 0.0, localmax,localmin;
  3955. char temp[200], temp2[200];
  3956. temp[0] = ENDOFSTR;
  3957. lastamp = dz->specenvfrq[0];
  3958. for(n=0;n<dz->specenvcnt;n++) {
  3959. switch(n) {
  3960. case(0):
  3961. thismaxamp = dz->specenvamp[n];
  3962. thisminamp = dz->specenvamp[n];
  3963. break;
  3964. case(1):
  3965. if(dz->specenvamp[n] > lastamp) {
  3966. sprintf(temp2,"%.1lf",dz->flbufptr[0][vc+1]); // Lowest frq in infile
  3967. pad = 14 - strlen(temp2);
  3968. for(k = 0;k < pad;k++)
  3969. strcat(temp2," ");
  3970. strcat(temp,temp2);
  3971. trofcnt++;
  3972. thismaxamp = dz->specenvamp[n];
  3973. rising = 1;
  3974. } else {
  3975. thisminamp = dz->specenvamp[n];
  3976. rising = 0;
  3977. }
  3978. default:
  3979. if(rising) {
  3980. if(dz->specenvamp[n] > lastamp)
  3981. thismaxamp = dz->specenvamp[n];
  3982. else {
  3983. localmax = -HUGE;
  3984. for(k = 0;k < dz->formant_bands; k++, vc+=2) {
  3985. if(dz->flbufptr[0][AMPP] > localmax) {
  3986. localmax = dz->flbufptr[0][AMPP];
  3987. localmaxat = vc;
  3988. }
  3989. }
  3990. sprintf(temp2,"%.1lf",dz->flbufptr[0][localmaxat+1]);
  3991. pad = 14 - strlen(temp2);
  3992. for(k = 0;k < pad;k++)
  3993. strcat(temp2," ");
  3994. strcat(temp,temp2);
  3995. peakcnt++;
  3996. thisminamp = dz->specenvamp[n];
  3997. rising = 0;
  3998. }
  3999. } else { // falling
  4000. if(dz->specenvamp[n] < lastamp)
  4001. thisminamp = dz->specenvamp[n];
  4002. else {
  4003. localmin = HUGE;
  4004. for(k = 0;k < dz->formant_bands; k++, vc+=2) {
  4005. if(dz->flbufptr[0][AMPP] < localmin) {
  4006. localmin = dz->flbufptr[0][AMPP];
  4007. localminat = vc;
  4008. }
  4009. }
  4010. if(trofcnt>0)
  4011. sprintf(temp2,"%.1lf",dz->flbufptr[0][localminat+1]);
  4012. else
  4013. sprintf(temp2,"%.1lf",dz->flbufptr[0][localminat+1]);
  4014. if(++trofcnt == 5) {
  4015. strcat(temp,temp2);
  4016. done = 1;
  4017. } else {
  4018. pad = 14 - strlen(temp2);
  4019. for(k = 0;k < pad;k++)
  4020. strcat(temp2," ");
  4021. strcat(temp,temp2);
  4022. thisminamp = dz->specenvamp[n];
  4023. rising = 1;
  4024. }
  4025. }
  4026. }
  4027. break;
  4028. }
  4029. if(done)
  4030. break;
  4031. lastamp = dz->specenvamp[n];
  4032. }
  4033. if(trofcnt < 5) {
  4034. if(!dz->warned) {
  4035. fprintf(stdout,"WARNING: At least one window has insufficient peaks (less than 4).\n");
  4036. fprintf(dz->fp,"INSUFFICIENT PEAKS\n");
  4037. dz->warned = 1;
  4038. }
  4039. } else {
  4040. sprintf(temp2,"\n");
  4041. strcat(temp,temp2);
  4042. fprintf(dz->fp,temp);
  4043. }
  4044. return(FINISHED);
  4045. }
  4046. /********************* FORMANTS_NEGATE *************************/
  4047. int formants_negate(int contourcnt,dataptr dz)
  4048. {
  4049. int exit_status, cc, vc;
  4050. double minamp, maxamp, ampsum, amp, amp2, pre_amptotal = 0.0, post_amptotal = 0.0;
  4051. float frq;
  4052. if((exit_status = extract_contour(contourcnt,dz))<0)
  4053. return exit_status;
  4054. if((exit_status = remember_contouramp(contourcnt,dz))<0)
  4055. return exit_status;
  4056. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  4057. return(exit_status);
  4058. maxamp = -HUGE;
  4059. minamp = HUGE;
  4060. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) { // Find max and min amplitudes of this window
  4061. minamp = min(minamp,dz->flbufptr[0][AMPP]);
  4062. maxamp = max(maxamp,dz->flbufptr[0][AMPP]);
  4063. }
  4064. ampsum = maxamp + minamp;
  4065. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) // stepup-inside-ampdiff = X - min: newval uses this as stepdn-within-ampdiff = max - stepup
  4066. dz->flbufptr[0][AMPP] = (float)ampsum - dz->flbufptr[0][AMPP]; // = max - (X - min) = max + min - X = ampsum - X !!
  4067. if(!dz->vflag[FLATT]) {
  4068. if((exit_status = extract_contour(contourcnt,dz))<0)
  4069. return exit_status;
  4070. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  4071. frq = dz->flbufptr[0][FREQ];
  4072. getcontouramp(&amp,contourcnt,frq,dz); // Contour now
  4073. getcontouramp2(&amp2,contourcnt,frq,dz); // Contour before
  4074. if(amp2 < VERY_TINY_VAL)
  4075. dz->flbufptr[0][AMPP] = 0.0f;
  4076. else
  4077. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * amp/amp2);
  4078. }
  4079. }
  4080. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  4081. return(exit_status);
  4082. if(post_amptotal > pre_amptotal) {
  4083. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  4084. return(exit_status);
  4085. }
  4086. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  4087. for(vc=0;vc<dz->wanted;vc+=2)
  4088. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  4089. }
  4090. return FINISHED;
  4091. }
  4092. /*********************** SPECFNU_PREPROCESS **********************/
  4093. int specfnu_preprocess(dataptr dz)
  4094. {
  4095. int exit_status, n, m;
  4096. dz->warned = 0;
  4097. dz->ischange = 1;
  4098. dz->in_tune = pow(SEMITONE_INTERVAL,WITHIN_RANGE);
  4099. switch(dz->mode) {
  4100. case(F_SEE): // fall thro
  4101. case(F_SEEPKS): // fall thro
  4102. case(F_SYLABTROF): // fall thro
  4103. return FINISHED;
  4104. case(F_ARPEG): // fall thro
  4105. case(F_OCTSHIFT): // fall thro
  4106. case(F_TRANS): // fall thro
  4107. case(F_FRQSHIFT): // fall thro
  4108. case(F_RESPACE): // fall thro
  4109. case(F_PINVERT): // fall thro
  4110. case(F_PEXAGG): // fall thro
  4111. case(F_PQUANT): // fall thro
  4112. case(F_PCHRAND): // fall thro
  4113. case(F_RAND):
  4114. dz->phasefactor = dz->frametime; // Arpeggiation sweeps 0 & 1
  4115. if((dz->iparray[ISHARM] = (int *)malloc(dz->clength * sizeof(int)))==NULL) {
  4116. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonics markers.\n");
  4117. return(MEMORY_ERROR);
  4118. }
  4119. return FINISHED;
  4120. case(F_NARROW): // Narrowing by 10 shrinks formantsize to 1/10
  4121. if(dz->brksize[NARROWING]) {
  4122. for(n=0,m=1;n<dz->brksize[NARROWING];n++,m+=2)
  4123. dz->brk[NARROWING][m] = 1.0/dz->brk[NARROWING][m];
  4124. } else
  4125. dz->param[NARROWING] = 1.0/dz->param[NARROWING];
  4126. dz->warned = 0;
  4127. break;
  4128. case(F_SQUEEZE): // Squeeze by 10 shrinks spectrum by 1/10
  4129. if(dz->brksize[SQZFACT]) {
  4130. for(n=0,m=1;n<dz->brksize[SQZFACT];n++,m+=2)
  4131. dz->brk[SQZFACT][m] = 1.0/dz->brk[SQZFACT][m];
  4132. } else
  4133. dz->param[SQZFACT] = 1.0/dz->param[SQZFACT];
  4134. dz->warned = 0;
  4135. break;
  4136. case(F_INVERT): // Variation is sinusoidal
  4137. dz->phasefactor = TWOPI * dz->frametime;// At 1Hz, we advance 2PI in 1 sec, so we advance 2PI * frametime in frametime-secs
  4138. break; // At 10Hz,we advance 2PI * 10 in 1 sec, so we advance 2PI * 10 * frametime in frametime-secs
  4139. case(F_ROTATE): // Variation sweeps through formants range from "0" to "1"
  4140. dz->phasefactor = dz->frametime; // At 1Hz, we advance by 1 in 1 sec, so we advance 1 * frametime in frametime-secs
  4141. break; // At 10Hz,we advance 10 in 1 sec, so we advance 10 * frametime in frametime-secs
  4142. case(F_MAKEFILT): // Creates array to store pitches to use in filter
  4143. if((dz->parray[FILTPICH] = (double *)malloc(dz->iparam[FPKCNT] * 4 * dz->timeblokcnt * sizeof(double)))==NULL) {
  4144. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitches data.\n");
  4145. return(MEMORY_ERROR);
  4146. }
  4147. if((dz->parray[FILTAMP] = (double *)malloc(dz->iparam[FPKCNT] * 4 * dz->timeblokcnt * sizeof(double)))==NULL) {
  4148. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Amps data.\n");
  4149. return(MEMORY_ERROR);
  4150. }
  4151. if((dz->parray[LOCALPCH] = (double *)malloc(dz->iparam[FPKCNT] * 4 * sizeof(double)))==NULL) {
  4152. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitches data.\n");
  4153. return(MEMORY_ERROR);
  4154. }
  4155. if((dz->parray[LOCALAMP] = (double *)malloc(dz->iparam[FPKCNT] * 4 * sizeof(double)))==NULL) {
  4156. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Amps data.\n");
  4157. return(MEMORY_ERROR);
  4158. }
  4159. break;
  4160. case(F_MOVE):
  4161. case(F_MOVE2):
  4162. for(n = FAMP1; n < PKSARRAYCNT; n++) {
  4163. if((dz->fptr[n] = (float *)malloc(dz->specenvcnt * sizeof(float)))==NULL) {
  4164. sprintf(errstr,"INSUFFICIENT MEMORY to store Intermediate formant data %d.\n",n+1);
  4165. return(MEMORY_ERROR);
  4166. }
  4167. }
  4168. for(n = FMULT;n < PRE_P_ARRAYCNT; n++) {
  4169. if((dz->parray[n] = (double *)malloc(dz->clength * sizeof(double)))==NULL) {
  4170. sprintf(errstr,"INSUFFICIENT MEMORY to store Intermediate formant double-data, item %d.\n",n+1);
  4171. return(MEMORY_ERROR);
  4172. }
  4173. }
  4174. if((dz->iparray[FCNT] = (int *)malloc(5 * sizeof(int)))==NULL) {
  4175. sprintf(errstr,"INSUFFICIENT MEMORY to store Intermediate dformant array data counts.\n");
  4176. return(MEMORY_ERROR);
  4177. }
  4178. dz->ischange = 0;
  4179. break;
  4180. case(F_SINUS):
  4181. for(n=0,m = FOR_FRQ1;n < P_SINUS_ARRAYS; n++,m++) {
  4182. if((dz->fptr[m] = (float *)malloc(dz->wlength * sizeof(float)))==NULL) { // 4 arrays store pitch-tracks of 4 formants
  4183. sprintf(errstr,"INSUFFICIENT MEMORY to store Formant %d pitch-tracks.\n",n+1); // 4 more arrays store smoothed or quantised tracks
  4184. return(MEMORY_ERROR); // & (later) related transposition values
  4185. }
  4186. }
  4187. for(n=0,m = F_CHTRAIN1;n < 9; n++,m++) { // 4 arrays store the (original) chanpositions
  4188. if((dz->iparray[m] = (int *)malloc(dz->wlength * sizeof(int)))==NULL) { // of the formant peakfrqs
  4189. sprintf(errstr,"INSUFFICIENT MEMORY to store Formant %d pitch-tracks.\n",n+1);
  4190. return(MEMORY_ERROR);
  4191. }
  4192. }
  4193. break;
  4194. }
  4195. if((exit_status = initialise_specenv2(dz)) < 0)
  4196. return exit_status;
  4197. if(dz->mode == F_NEGATE)
  4198. return FINISHED;
  4199. if((exit_status = initialise_peakstore(dz)) < 0)
  4200. return exit_status;
  4201. dz->pktrofcnt = PKBLOK; // We start counting aFTER 1 block of peaks, as window 1 has no PEAK info
  4202. dz->badpks = 0;
  4203. dz->zeroset = 0;
  4204. return FINISHED;
  4205. }
  4206. /*********************** GET_PEAKS_AND_TROFS **********************/
  4207. int get_peaks_and_trofs(int inner_lpcnt,int limit,int *previouspk,dataptr dz)
  4208. {
  4209. int exit_status, n, i, j, k, there, valid, rising = 0, done = 0;
  4210. int abscnt = dz->pktrofcnt, localcnt = 0, blokstep, ilpcnt;
  4211. float lastamp = 0.0;
  4212. double interp;
  4213. float *peaktrof = dz->fptr[PKTROF];
  4214. int *pos = dz->iparray[PEAKPOS];
  4215. float *pkdiff = dz->fptr[PKDIFF];
  4216. for(n=0;n<dz->specenvcnt;n++) {
  4217. switch(n) {
  4218. case(0):
  4219. break;
  4220. case(1):
  4221. if(dz->specenvamp[n] > lastamp) {
  4222. peaktrof[abscnt] = lastamp;
  4223. pos[abscnt] = n-1;
  4224. abscnt++;
  4225. localcnt++;
  4226. rising = 1;
  4227. } else
  4228. rising = 0;
  4229. break;
  4230. default:
  4231. if(rising) {
  4232. if(dz->specenvamp[n] < lastamp) {
  4233. peaktrof[abscnt] = lastamp;
  4234. pos[abscnt] = n-1;
  4235. abscnt++;
  4236. localcnt++;
  4237. rising = 0;
  4238. }
  4239. } else { // falling
  4240. if(dz->specenvamp[n] > lastamp) {
  4241. peaktrof[abscnt] = lastamp;
  4242. pos[abscnt] = n-1;
  4243. abscnt++;
  4244. localcnt++;
  4245. if(localcnt == PKBLOK) // 5 trofs and 4 peaks
  4246. done = 1;
  4247. else
  4248. rising = 1;
  4249. }
  4250. }
  4251. break;
  4252. }
  4253. if(done)
  4254. break;
  4255. lastamp = dz->specenvamp[n];
  4256. }
  4257. if(!done) {
  4258. dz->badpks = 1;
  4259. dz->pktrofcnt += PKBLOK;
  4260. if(dz->pktrofcnt >= limit) { // If we're at LAST window, and there are bad blocks, forwardfill with last valid vals
  4261. if(*previouspk < 0) {
  4262. sprintf(errstr,"No window has (the required) 4 peaks.\n");
  4263. return DATA_ERROR;
  4264. }
  4265. for(k = *previouspk + PKBLOK ;k < dz->pktrofcnt; k += PKBLOK) {
  4266. for(j = 0,there = k, valid = *previouspk; j < PKBLOK; j++,there++,valid++)
  4267. peaktrof[there] = peaktrof[valid];
  4268. if(dz->mode == F_SINUS) {
  4269. ilpcnt = k/PKBLOK;
  4270. if((exit_status = store_formant_frq_data(ilpcnt,dz))<0)
  4271. return (exit_status);
  4272. }
  4273. }
  4274. return FINISHED;
  4275. }
  4276. }
  4277. else {
  4278. if(dz->badpks) {
  4279. if(*previouspk < 0) { // Backfill non-peak bloks at start with same vals as 1st true peakblok found
  4280. for(k = 0;k < dz->pktrofcnt; k += PKBLOK) {
  4281. for(j = 0,there = k, valid = dz->pktrofcnt; j < PKBLOK; j++,there++,valid++)
  4282. peaktrof[there] = peaktrof[valid];
  4283. if(dz->mode == F_SINUS) {
  4284. ilpcnt = k/PKBLOK;
  4285. if((exit_status = store_formant_frq_data(ilpcnt,dz))<0)
  4286. return (exit_status);
  4287. }
  4288. }
  4289. } else { // Or infill non-peak bloks with interp of existing peakbloks
  4290. for(j = 0;j < PKBLOK; j++) // Get differences between peak and trogfs vals in the 2 valid pkbloks
  4291. pkdiff[j] = (float)(peaktrof[dz->pktrofcnt + j] - peaktrof[*previouspk + j]);
  4292. blokstep = (dz->pktrofcnt - *previouspk)/PKBLOK; // Find number of bad blocks
  4293. for(k = *previouspk + PKBLOK, i = 1;k < dz->pktrofcnt; k += PKBLOK, i++) {
  4294. interp = (double)i/(double)blokstep; // Set interp porportion
  4295. for(j = 0,there = k; j < PKBLOK; j++,there++) // Write in interpd values
  4296. peaktrof[there] = (float)(peaktrof[*previouspk + k] + (pkdiff[j] * interp));
  4297. }
  4298. }
  4299. dz->badpks = 0;
  4300. }
  4301. *previouspk = dz->pktrofcnt;
  4302. if(dz->mode == F_SINUS) {
  4303. if((exit_status = store_formant_frq_data(inner_lpcnt,dz))<0)
  4304. return (exit_status);
  4305. }
  4306. dz->pktrofcnt += PKBLOK;
  4307. if(dz->pktrofcnt >= limit)
  4308. return FINISHED;
  4309. }
  4310. return CONTINUE;
  4311. }
  4312. /****************************************** INITIALISE_PEAKSTORE ************************************/
  4313. int initialise_peakstore(dataptr dz)
  4314. {
  4315. if((dz->fptr[PKTROF] = (float *)malloc((dz->wlength + 2) * PKBLOK * sizeof(float)))==NULL) { // +2 = SAFETY
  4316. sprintf(errstr,"INSUFFICIENT MEMORY for store of window peaks and troughs(2).\n");
  4317. return(MEMORY_ERROR);
  4318. }
  4319. if((dz->fptr[PKDIFF] = (float *)malloc(PKBLOK * sizeof(float)))==NULL) {
  4320. sprintf(errstr,"INSUFFICIENT MEMORY for store of differences between window peaks and troughs.\n");
  4321. return(MEMORY_ERROR);
  4322. }
  4323. if((dz->iparray[PEAKPOS] = (int *)malloc(dz->wlength * PKBLOK * sizeof(int)))==NULL) {
  4324. sprintf(errstr,"INSUFFICIENT MEMORY for store of locations of peaks and troughs(2).\n");
  4325. return(MEMORY_ERROR);
  4326. }
  4327. return FINISHED;
  4328. }
  4329. /************************** GET_FMAX ***********************/
  4330. int get_fmax(double *fmax,dataptr dz)
  4331. {
  4332. int n;
  4333. for(n = 0; n < dz->specenvcnt;n++)
  4334. *fmax = max(dz->specenvamp[n],*fmax);
  4335. return FINISHED;
  4336. }
  4337. /**************************** HANDLE_THE_MAKEFILT_SPECIAL_DATA ****************************/
  4338. int handle_the_makefilt_special_data(char *str,dataptr dz)
  4339. {
  4340. int is_hs = -1, is_pitches = 0, is_scale = 0, is_elacs = 0, scale_division = 12, ignore_further_times = 0;
  4341. int cnttimes = 0, cntpitches = 0, linecnt, pitchpos, oct1pitchpos, step, n, m,k, offset, done, mindiffat, nubincnt, timepos, trueoct_cnt;
  4342. double dummy = 0.0, reference_pitch = 60.0, lasttime = 0.0, ratio, octstep, nextpitch, mindiff, thisdiff, nupitch;
  4343. double pseudoct_size = 12.0, semitone_len, thispitch, octfoot = 0.0;
  4344. FILE *fp;
  4345. double *prepitch = NULL, *binpitch = NULL, *bintop = NULL;
  4346. int arraysize, *ftime;
  4347. char temp[800], *p;
  4348. if((fp = fopen(str,"r"))==NULL) {
  4349. sprintf(errstr,"Cannot open file %s to read data.\n",str);
  4350. return(DATA_ERROR);
  4351. }
  4352. linecnt = 0;
  4353. while(fgets(temp,200,fp)!=NULL) {
  4354. p = temp;
  4355. while(isspace(*p))
  4356. p++;
  4357. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  4358. continue;
  4359. if(*p == '#') { // Look for #HF, #HS, or #SCALES marker
  4360. if(cnttimes == 0) {
  4361. sprintf(errstr,"No time segmentation specified in file %s.\n",str);
  4362. return(DATA_ERROR);
  4363. }
  4364. if(strncmp(p,"#HS",3) == 0) {
  4365. is_hs = 1;
  4366. is_pitches = 1;
  4367. } else if(strncmp(p,"#HF",3) == 0) {
  4368. is_hs = 0;
  4369. is_pitches = 1;
  4370. } else if(strncmp(p,"#SCALE",6) == 0) {
  4371. is_hs = 0;
  4372. is_scale = 1;
  4373. is_pitches = 1;
  4374. } else if(strncmp(p,"#ELACS",6) == 0) {
  4375. is_hs = 0;
  4376. is_elacs = 1;
  4377. is_pitches = 1;
  4378. }
  4379. else {
  4380. sprintf(errstr,"Invalid Field, Set, or Scale marker (%s) on line %d in file %s\n",linecnt+1,p,str);
  4381. return(DATA_ERROR);
  4382. }
  4383. } else {
  4384. while(get_float_from_within_string(&p,&dummy)) {
  4385. if(is_pitches) {
  4386. if(is_scale) { // For scales, we need to find note-per-oct and ref-pitch
  4387. switch(cntpitches) {
  4388. case(0):
  4389. if(dummy < 1 || dummy > MAXSCALECNT) {
  4390. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4391. return(DATA_ERROR);
  4392. }
  4393. scale_division = (int)round(dummy);
  4394. break;
  4395. case(1):
  4396. if(dummy < 0 || dummy > MIDIMAX) {
  4397. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4398. return(DATA_ERROR);
  4399. }
  4400. reference_pitch = dummy;
  4401. break;
  4402. default:
  4403. sprintf(errstr,"Too many vals specified for scale in file %s: need only notes-per-octave and (MIDI)ref-pitch.\n",str);
  4404. return(DATA_ERROR);
  4405. }
  4406. } else if(is_elacs) { // For elacs, we need to find "octave"-size,note-per-oct and ref-pitch
  4407. switch(cntpitches) {
  4408. case(0):
  4409. if(dummy < PSEUDOCTMIN || dummy > PSEUDOCTMAX) {
  4410. sprintf(errstr,"\"Octave\" size (%d) at line %d out of range (%d to %d)\n",(int)round(dummy),linecnt+1,PSEUDOCTMIN,PSEUDOCTMAX);
  4411. return(DATA_ERROR);
  4412. }
  4413. pseudoct_size = (int)round(dummy);
  4414. break;
  4415. case(1):
  4416. if(dummy < 1 || dummy > MAXSCALECNT) {
  4417. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4418. return(DATA_ERROR);
  4419. }
  4420. scale_division = (int)round(dummy);
  4421. if((double)pseudoct_size/(double)scale_division < .01) {
  4422. sprintf(errstr,"Scale steps per true octave (%.lf) too small (Minimum %.2lf)\n",(double)pseudoct_size/(double)scale_division,0.01);
  4423. return(DATA_ERROR);
  4424. }
  4425. break;
  4426. case(2):
  4427. if(dummy < 0 || dummy > MIDIMAX) {
  4428. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4429. return(DATA_ERROR);
  4430. }
  4431. reference_pitch = dummy;
  4432. break;
  4433. default:
  4434. sprintf(errstr,"Too many vals for escal in file %s: need only \"oct\"-size, notes-per-\"oct\" and (MIDI)ref-pitch.\n",str);
  4435. return(DATA_ERROR);
  4436. }
  4437. } else { // For HS or HF we need a set of MIDI values
  4438. if(dummy < 0 || dummy > MIDIMAX) {
  4439. sprintf(errstr,"Invalid pitch data (%lf) at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4440. return(DATA_ERROR);
  4441. }
  4442. }
  4443. cntpitches++;
  4444. } else {
  4445. if(ignore_further_times) // If ignoring times, keep reading till we reach HF/HS data
  4446. continue;
  4447. if(cnttimes == 0.0) {
  4448. if(dummy < 0) {
  4449. sprintf(errstr,"Invalid time (%lf) at line %d in file %s.\n",dummy,linecnt+1,str);
  4450. return(DATA_ERROR);
  4451. } // If 1st time val at or after file end, Ignore it and further time-values
  4452. if(dummy >= dz->duration) {
  4453. fprintf(stdout,"WARNING: First time (%lf) at or beyond file end (%lf): will use unsegmented src.\n",dummy,dz->duration);
  4454. fflush(stdout);
  4455. ignore_further_times = 1;
  4456. }
  4457. } else { // Ensure time-markers increase
  4458. if (dummy <= lasttime) {
  4459. sprintf(errstr,"Times do not advance (%lf to %lf) at from line %d to line %d\n",lasttime,dummy,linecnt,linecnt+1);
  4460. return(DATA_ERROR);
  4461. } // Ignore any time markers at or after file end
  4462. if(dummy >= dz->duration) {
  4463. fprintf(stdout,"WARNING: Time (%lf) at line %d is at or beyond file end (%lf): ignoring it (and later times)\n",dummy,linecnt+1,dz->duration);
  4464. fflush(stdout);
  4465. cnttimes--; // Counters the increment in "cnttimes" below
  4466. ignore_further_times = 1;
  4467. }
  4468. }
  4469. lasttime = dummy;
  4470. cnttimes++;
  4471. }
  4472. }
  4473. }
  4474. }
  4475. if(cnttimes == 0) { // Should be redundant
  4476. sprintf(errstr,"No time-segmentation specified, in file %s.\n",str);
  4477. return(DATA_ERROR);
  4478. }
  4479. if(is_hs == -1) {
  4480. sprintf(errstr,"No data for Harmonic-Field, Harmonic-Set or Scale-type specified in file %s.\n",str);
  4481. return(DATA_ERROR);
  4482. }
  4483. if(is_scale || is_elacs) {
  4484. if(is_scale) {
  4485. arraysize = (scale_division * MIDIOCTSPAN) + 1;
  4486. if((dz->parray[PBINPCH] = (double *)malloc(arraysize * 4 * sizeof(double)))==NULL) {
  4487. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4488. return(MEMORY_ERROR);
  4489. }
  4490. binpitch = dz->parray[PBINPCH];
  4491. pitchpos = 0; // Dummy entry in position [0] - (allows pitchtop counter to tally with pitch centre conter)
  4492. binpitch[pitchpos++] = 0.0;
  4493. // SPECIFY PITCHES IN 1ST 8VA
  4494. switch(scale_division) {
  4495. case(1):// fall thro // For rational divisors of 12
  4496. case(2):// fall thro
  4497. case(3):// fall thro
  4498. case(4):// fall thro
  4499. case(6):// fall thro
  4500. case(12):
  4501. step = (int)round(SEMITONES_PER_OCTAVE)/scale_division;
  4502. for(n = 0;n < scale_division;n+=step)
  4503. binpitch[pitchpos++] = (double)n;
  4504. break;
  4505. default: // Otherwise
  4506. for(n = 0;n < scale_division;n++) {
  4507. ratio = (double)n/(double)scale_division;
  4508. binpitch[pitchpos++] = SEMITONES_PER_OCTAVE * ratio;
  4509. }
  4510. break;
  4511. }
  4512. // SPECIFY PITCHES IN ALL OTHER 8VAs
  4513. done = 0;
  4514. octstep = 0;
  4515. for(m=1;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  4516. oct1pitchpos = 1; // Point to vals in lowest 8va
  4517. octstep += SEMITONES_PER_OCTAVE;
  4518. for(n=0;n<scale_division;n++) { // Copy these, N octaves higher, into higher octaves
  4519. nextpitch = binpitch[oct1pitchpos++] + octstep;
  4520. if(nextpitch > MIDIMAX) {
  4521. done = 1;
  4522. break;
  4523. }
  4524. binpitch[pitchpos++] = nextpitch;
  4525. }
  4526. if(done)
  4527. break;
  4528. }
  4529. dz->bincnt = pitchpos; // Remember how many bins we have
  4530. } else { // is_elacs
  4531. arraysize = 0;
  4532. trueoct_cnt = 0;
  4533. semitone_len = 0;
  4534. while(trueoct_cnt < MIDIOCTSPAN) {
  4535. arraysize += scale_division;
  4536. semitone_len += pseudoct_size;
  4537. trueoct_cnt = (int)floor(semitone_len/SEMITONES_PER_OCTAVE);
  4538. }
  4539. if((dz->parray[PBINPCH] = (double *)malloc(arraysize * 4 * sizeof(double)))==NULL) {
  4540. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4541. return(MEMORY_ERROR);
  4542. }
  4543. binpitch = dz->parray[PBINPCH];
  4544. pitchpos = 0; // Dummy entry in position [0] - (allows pitchtop counter to tally with pitch centre conter)
  4545. binpitch[pitchpos++] = 0.0;
  4546. // SPECIFY PITCHES IN EACH pseudo8va Ffor all pseudo8vas until MIDIMAX is reached
  4547. thispitch = 0.0;
  4548. octfoot = 0.0;
  4549. while(thispitch <= MIDIMAX) {
  4550. for(n = 0;n < scale_division;n++) {
  4551. ratio = (double)n/(double)scale_division;
  4552. if((thispitch = (pseudoct_size * ratio) + octfoot) > MIDIMAX) {
  4553. break;
  4554. }
  4555. binpitch[pitchpos++] = thispitch;
  4556. }
  4557. octfoot += pseudoct_size;
  4558. }
  4559. dz->bincnt = pitchpos; // Remember how many bins we have
  4560. }
  4561. if(is_elacs || !flteq(fmod(reference_pitch,SEMITONES_PER_OCTAVE),0.0)) { // Either, is_elacs, so pitches not guaranteed to include reference_pitch
  4562. // OR, Reference-pitch is not at multiple of 12
  4563. // Find pitch closest to reference pitch, and find interval distance to ref-pitch
  4564. mindiff = HUGE;
  4565. mindiffat = 0;
  4566. for(n = 1; n < dz->bincnt; n++) { // binpitch[0] is a dummy
  4567. thisdiff = fabs(reference_pitch - binpitch[n]);
  4568. if(thisdiff < mindiff) {
  4569. mindiff = thisdiff;
  4570. mindiffat = n;
  4571. }
  4572. }
  4573. // Now transpose set so it includes ref-pitch
  4574. mindiff = reference_pitch - binpitch[mindiffat];
  4575. if(mindiff > 0.0) {
  4576. for(n = 1; n < dz->bincnt; n++) {
  4577. nupitch = binpitch[n] + mindiff;
  4578. if(nupitch > 127)
  4579. break;
  4580. binpitch[n] = nupitch;
  4581. }
  4582. dz->bincnt = n; // May be smaller than orig, if binpitch pushed eyond 127
  4583. } else if(mindiff < 0.0) {
  4584. nubincnt = 1;
  4585. for(n = 1; n < dz->bincnt; n++) {
  4586. nupitch = binpitch[n] + mindiff;
  4587. if(nupitch >= 0.0) // binpitch now below zero are ignored, so the new bincnt (m) does not increment
  4588. binpitch[nubincnt++] = nupitch; // Otherwise new binpitch are written over orig binpitch (possibly lower in array - but never higher!!)
  4589. }
  4590. dz->bincnt = nubincnt;
  4591. }
  4592. }
  4593. if((dz->iparray[PCNTBIN] = (int *)malloc(dz->bincnt * 4 * sizeof(int)))==NULL) {
  4594. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Counting Data.\n");
  4595. return(MEMORY_ERROR);
  4596. }
  4597. if((dz->parray[PBINTOP] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  4598. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Top Data.\n");
  4599. return(MEMORY_ERROR);
  4600. }
  4601. if((dz->parray[PBINAMP] = (double *)malloc(dz->bincnt * 4 * sizeof(double)))==NULL) {
  4602. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Amp Data.\n");
  4603. return(MEMORY_ERROR);
  4604. }
  4605. } else {
  4606. // If not scale: create array to store pitchdata initially read from file
  4607. if((dz->parray[PREPICH] = (double *)malloc((cntpitches + 1) * sizeof(double)))==NULL) {
  4608. sprintf(errstr,"INSUFFICIENT MEMORY to store Initial Filter Pitch Data.\n");
  4609. return(MEMORY_ERROR);
  4610. }
  4611. prepitch = dz->parray[PREPICH];
  4612. }
  4613. arraysize = cnttimes;
  4614. arraysize+=2; // Need (possibly) to insert time at 0.0, and at end;
  4615. if((dz->lparray[FTIMES] = (int *)malloc(arraysize * sizeof(int)))==NULL) {
  4616. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter Times Data.(2)\n");
  4617. return(MEMORY_ERROR);
  4618. }
  4619. ftime = dz->lparray[FTIMES];
  4620. timepos = 0;
  4621. ftime[timepos++] = 0;
  4622. rewind(fp);
  4623. is_pitches = 0;
  4624. linecnt = 0;
  4625. cntpitches = 0;
  4626. while(fgets(temp,200,fp)!=NULL) {
  4627. p = temp;
  4628. while(isspace(*p))
  4629. p++;
  4630. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  4631. continue;
  4632. if(*p == '#') {
  4633. if(is_scale) // If HF/HS data is a scale, we already have the pitch data: so quit
  4634. break;
  4635. is_pitches = 1;
  4636. continue;
  4637. } else {
  4638. while(get_float_from_within_string(&p,&dummy)) {
  4639. if(is_pitches)
  4640. prepitch[cntpitches++] = dummy;
  4641. else {
  4642. if(ignore_further_times)
  4643. continue;
  4644. if(dummy >= dz->duration) {
  4645. ignore_further_times = 1; // Defaults to the zero val already in array
  4646. continue;
  4647. }
  4648. if(timepos == 1 && flteq(dummy,0.0))
  4649. continue; // Already got time zero in times array, but may be other times to store
  4650. ftime[timepos++] = (int)round(dummy/dz->frametime);
  4651. }
  4652. }
  4653. }
  4654. }
  4655. if(ftime[timepos-1] > dz->wlength - MINWINDOWS) // If last time very close to endoffile
  4656. ftime[timepos-1] = dz->wlength + 1; // move it to AFTER end of file
  4657. else { // If not, add another point AFTER end of file
  4658. ftime[timepos] = dz->wlength + 1;
  4659. timepos++;
  4660. }
  4661. dz->timeblokcnt = timepos - 1; // If we have 5 times: 0 X Y Z END we have 4 bloks: 0-X: X-Y: Y-Z: Z-END
  4662. fclose(fp);
  4663. if(!is_scale) {
  4664. dz->itemcnt = cntpitches;
  4665. dz->itemcnt = sort_pitches(dz); // Some pitches may be duplicated: they also need to be in ascending order
  4666. if(is_hs)
  4667. dz->bincnt = dz->itemcnt + 1; // Space for all entered pitches + dummy value at [0]
  4668. else {
  4669. for(n = 0;n < dz->itemcnt; n++) { // For HF, duplicate pitches over all 8vas
  4670. while(prepitch[n] > 0.0)
  4671. prepitch[n] -= SEMITONES_PER_OCTAVE; // 1st transpose all pitches into lowest octave
  4672. prepitch[n] += SEMITONES_PER_OCTAVE;
  4673. }
  4674. dz->itemcnt = sort_pitches(dz); // After transposition, some pitches may be duplicated
  4675. dz->bincnt = (dz->itemcnt * MIDIOCTSPAN) + 1; // pitches are to be duplicated in all 8vas + we need the dummy val at [0]
  4676. }
  4677. if((dz->parray[PBINPCH] = (double *)malloc(dz->bincnt * 4 * sizeof(double)))==NULL) {
  4678. sprintf(errstr,"INSUFFICIENT MEMORY to store Pitch-Bin-Top data.\n");
  4679. return(MEMORY_ERROR);
  4680. }
  4681. binpitch = dz->parray[PBINPCH];
  4682. if(is_hs) { // For HS, merely copy pitches into final array, leaving dummy value at [0]
  4683. memcpy((char *)(dz->parray[PBINPCH] + 1),(char *)dz->parray[PREPICH],(dz->bincnt - 1) * sizeof(double));
  4684. dz->parray[PBINPCH][0] = 0.0;
  4685. } else { // For HF, copy pitches into all 8vas in MIDI range
  4686. done = 0;
  4687. pitchpos = 0;
  4688. binpitch[pitchpos++] = 0.0; // Leave dummy value at zero
  4689. octstep = 0;
  4690. for(m=0;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  4691. for(n=0;n<dz->itemcnt;n++) { // Copy pitches in lowest octave into higher octaves
  4692. nextpitch = prepitch[n] + octstep;
  4693. if(nextpitch > MIDIMAX) {
  4694. done = 1;
  4695. break;
  4696. }
  4697. binpitch[pitchpos++] = nextpitch;
  4698. }
  4699. octstep += SEMITONES_PER_OCTAVE;
  4700. if(done)
  4701. break;
  4702. }
  4703. dz->bincnt = pitchpos; // Remember how many bins we have
  4704. }
  4705. if((dz->parray[PBINTOP] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  4706. sprintf(errstr,"INSUFFICIENT MEMORY to store Pitch-Bin-Top data.\n");
  4707. return(MEMORY_ERROR);
  4708. }
  4709. if((dz->parray[PBINAMP] = (double *)malloc(dz->bincnt * 4 * sizeof(double)))==NULL) {
  4710. sprintf(errstr,"INSUFFICIENT MEMORY to store Pitch-Bin-Amp Data.\n");
  4711. return(MEMORY_ERROR);
  4712. }
  4713. if((dz->iparray[PCNTBIN] = (int *)malloc(dz->bincnt * 4 * sizeof(int)))==NULL) {
  4714. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Counting Data.\n");
  4715. return(MEMORY_ERROR);
  4716. }
  4717. }
  4718. // Establish the pitch boundaries of the pitch bins (Bins are NO MORE than a semitone in width, and may be less if steps between pitches less than a semitone)
  4719. bintop = dz->parray[PBINTOP];
  4720. for(m=1;m< 4;m++) {
  4721. offset = dz->bincnt * m; // 4 arrays, 1 for each formant
  4722. for(n=0,k=offset;n<dz->bincnt;n++,k++)
  4723. binpitch[k] = binpitch[n];
  4724. }
  4725. for(n=1;n < dz->bincnt-1;n++) { // For HS gaps width of pitch-search bins assumed to be a semitone
  4726. bintop[n] = min((binpitch[n+1] - binpitch[n])/2.0,0.5); // (or less, of gap between bins is less than a semitone)
  4727. bintop[n] += binpitch[n];
  4728. }
  4729. bintop[n] = binpitch[n] + (binpitch[n] - bintop[n-1]); // Upper Bound of topmost pitchbin assumed to be same distance from centre as its lower bound
  4730. bintop[n] = min(127.0,bintop[n]); // Unless that takes it above 127
  4731. bintop[0] = binpitch[1] - (bintop[1] - binpitch[1]); // Lower bound (pitchtop[0]) of lowest bin (binpitch[1]) same distance from centre as upper bound
  4732. bintop[0] = max(0.0,bintop[0]); // Unless that takes it below zero
  4733. memset((char *)dz->iparray[PCNTBIN],0,dz->bincnt * 4 *sizeof(int)); // Preset arrays where values are ADDED into them
  4734. memset((double *)dz->parray[PBINAMP],0,dz->bincnt * 4 * sizeof(double));
  4735. if((dz->parray[FPITCHES] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  4736. sprintf(errstr,"INSUFFICIENT MEMORY to store pitches actually used by filter.\n");
  4737. return(MEMORY_ERROR);
  4738. }
  4739. return FINISHED;
  4740. }
  4741. /**************************** HANDLE_THE_PQUANTISE_SPECIAL_DATA ****************************/
  4742. int handle_the_pquantise_special_data(char *str,dataptr dz)
  4743. {
  4744. int exit_status, is_hs = -1, is_thf = 0, is_pitches = 0, is_scale = 0, is_elacs = 0, scale_division = 12, entrycnt = 0, pitchsort = 0;
  4745. int cntpitches = 0, linecnt, pitchpos, oct1pitchpos, step, n, m, done, mindiffat, nubincnt;
  4746. double dummy = 0.0, reference_pitch = 60.0, ratio, octstep, nextpitch, mindiff, thisdiff, nupitch, pseudoct_size = 12.0;
  4747. double trueoct_cnt, semitone_len, thispitch, octfoot, lasttime = 0.0;
  4748. FILE *fp;
  4749. double *pset = NULL, *prepitch;
  4750. int arraysize;
  4751. char temp[800], *p;
  4752. dz->timedhf = 0;
  4753. if((dz->mode == F_PCHRAND || dz->mode == F_SINUS) && (!strcmp(str,"0") || !strcmp(str,"0.0"))) {
  4754. dz->quantcnt = 0;
  4755. return FINISHED;
  4756. }
  4757. if((fp = fopen(str,"r"))==NULL) {
  4758. sprintf(errstr,"Cannot open file %s to read data.\n",str);
  4759. return(DATA_ERROR);
  4760. }
  4761. linecnt = 0;
  4762. while(fgets(temp,200,fp)!=NULL) {
  4763. p = temp;
  4764. while(isspace(*p))
  4765. p++;
  4766. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  4767. continue;
  4768. if(*p == '#') { // Look for #HF, #HS, or #SCALES marker
  4769. strip_end_space(p);
  4770. if(strcmp(p,"#HS") == 0) {
  4771. is_hs = 1;
  4772. is_pitches = 1;
  4773. } else if(strcmp(p,"#HF") == 0) {
  4774. is_hs = 0;
  4775. is_pitches = 1;
  4776. } else if(strcmp(p,"#SCALE") == 0) {
  4777. is_hs = 0;
  4778. is_scale = 1;
  4779. is_pitches = 1;
  4780. } else if(strcmp(p,"#ELACS") == 0) {
  4781. is_hs = 0;
  4782. is_elacs = 1;
  4783. is_pitches = 1;
  4784. } else if(strcmp(p,"#THF") == 0) {
  4785. is_hs = 0;
  4786. is_thf = 1;
  4787. dz->timedhf = 1;
  4788. is_pitches = 1;
  4789. }
  4790. else {
  4791. sprintf(errstr,"Invalid Field, Set, or Scale marker (%s) on line %d in file %s\n",p,linecnt+1,str);
  4792. return(DATA_ERROR);
  4793. }
  4794. } else {
  4795. while(get_float_from_within_string(&p,&dummy)) {
  4796. if(is_scale) { // For scales, we need to find note-per-oct and ref-pitch
  4797. switch(cntpitches) {
  4798. case(0):
  4799. if(dummy < 1 || dummy > MAXSCALECNT) {
  4800. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4801. return(DATA_ERROR);
  4802. }
  4803. scale_division = (int)round(dummy);
  4804. break;
  4805. case(1):
  4806. if(dummy < 0 || dummy > MIDIMAX) {
  4807. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4808. return(DATA_ERROR);
  4809. }
  4810. reference_pitch = dummy;
  4811. break;
  4812. default:
  4813. sprintf(errstr,"Too many vals specified for scale in file %s: need only notes-per-octave and (MIDI)ref-pitch.\n",str);
  4814. return(DATA_ERROR);
  4815. }
  4816. } else if(is_elacs) { // For elacs, we need to find "octave"-size,note-per-oct and ref-pitch
  4817. switch(cntpitches) {
  4818. case(0):
  4819. if(dummy < PSEUDOCTMIN || dummy > PSEUDOCTMAX) {
  4820. sprintf(errstr,"\"Octave\" size (%d) at line %d out of range (%d to %d)\n",(int)round(dummy),linecnt+1,PSEUDOCTMIN,PSEUDOCTMAX);
  4821. return(DATA_ERROR);
  4822. }
  4823. pseudoct_size = (int)round(dummy);
  4824. break;
  4825. case(1):
  4826. if(dummy < 1 || dummy > MAXSCALECNT) {
  4827. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4828. return(DATA_ERROR);
  4829. }
  4830. scale_division = (int)round(dummy);
  4831. if((double)pseudoct_size/(double)scale_division < .01) {
  4832. sprintf(errstr,"Scale steps per true octave (%.lf) too small (Minimum %.2lf)\n",(double)pseudoct_size/(double)scale_division,0.01);
  4833. return(DATA_ERROR);
  4834. }
  4835. break;
  4836. case(2):
  4837. if(dummy < 0 || dummy > MIDIMAX) {
  4838. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4839. return(DATA_ERROR);
  4840. }
  4841. reference_pitch = dummy;
  4842. break;
  4843. default:
  4844. sprintf(errstr,"Too many vals for escal in file %s: need only \"oct\"-size, notes-per-\"oct\" and (MIDI)ref-pitch.\n",str);
  4845. return(DATA_ERROR);
  4846. }
  4847. } else if(is_thf) { // For thf, we need to find several hfs and their times
  4848. if(entrycnt == 0)
  4849. pitchsort = cntpitches;
  4850. else
  4851. pitchsort = cntpitches % entrycnt;
  4852. switch(pitchsort) {
  4853. case(0):
  4854. if(linecnt == 1) {
  4855. if(dummy != 0.0) {
  4856. sprintf(errstr,"First time must be zero for a time-changing HF, in file %s\n",str);
  4857. return(DATA_ERROR);
  4858. }
  4859. } else if(dummy <= lasttime) {
  4860. sprintf(errstr,"Times do not advance (%lf : %lf) from line %d to line %d in file %s\n",lasttime,dummy,linecnt-1,linecnt,str);
  4861. return(DATA_ERROR);
  4862. }
  4863. lasttime = dummy;
  4864. break;
  4865. default:
  4866. if(dummy < 0.0 || dummy > 127) {
  4867. sprintf(errstr,"Pitch value (%lf) out of range (0-127) in %d in file %s\n",dummy,linecnt,str);
  4868. return(DATA_ERROR);
  4869. }
  4870. break;
  4871. }
  4872. } else { // For HS or HF we need a set of MIDI values
  4873. if(dummy < 0 || dummy > MIDIMAX) {
  4874. sprintf(errstr,"Invalid pitch data (%lf) at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4875. return(DATA_ERROR);
  4876. }
  4877. }
  4878. cntpitches++;
  4879. }
  4880. }
  4881. if(linecnt > 0 && is_thf) {
  4882. if(linecnt == 1)
  4883. entrycnt = cntpitches;
  4884. else if(cntpitches % entrycnt != 0) {
  4885. sprintf(errstr,"Lines %d & %d are not of same length in file %s\n",linecnt,linecnt+1,str);
  4886. return(DATA_ERROR);
  4887. }
  4888. }
  4889. linecnt++;
  4890. }
  4891. if(is_hs == -1) {
  4892. sprintf(errstr,"No data for Harmonic-Field, Harmonic-Set or Scale-type specified in file %s.\n",str);
  4893. return(DATA_ERROR);
  4894. }
  4895. if(is_scale || is_elacs) {
  4896. if(is_scale) {
  4897. arraysize = (scale_division * MIDIOCTSPAN) + 1;
  4898. if((dz->parray[QUANTPITCH] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
  4899. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4900. return(MEMORY_ERROR);
  4901. }
  4902. pset = dz->parray[QUANTPITCH];
  4903. pitchpos = 0;
  4904. // SPECIFY PITCHES IN 1ST 8VA
  4905. switch(scale_division) {
  4906. case(1):// fall thro // For rational divisors of 12
  4907. case(2):// fall thro
  4908. case(3):// fall thro
  4909. case(4):// fall thro
  4910. case(6):// fall thro
  4911. case(12):
  4912. step = (int)round(SEMITONES_PER_OCTAVE)/scale_division;
  4913. for(n = 0;n < scale_division;n+=step)
  4914. pset[pitchpos++] = (double)n;
  4915. break;
  4916. default: // Otherwise
  4917. for(n = 0;n < scale_division;n++) {
  4918. ratio = (double)n/(double)scale_division;
  4919. pset[pitchpos++] = SEMITONES_PER_OCTAVE * ratio;
  4920. }
  4921. break;
  4922. }
  4923. // SPECIFY PITCHES IN ALL OTHER 8VAs
  4924. done = 0;
  4925. octstep = 0;
  4926. for(m=1;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  4927. oct1pitchpos = 1; // Point to vals in lowest 8va
  4928. octstep += SEMITONES_PER_OCTAVE;
  4929. for(n=0;n<scale_division;n++) { // Copy these, N octaves higher, into higher octaves
  4930. nextpitch = pset[oct1pitchpos++] + octstep;
  4931. if(nextpitch > MIDIMAX) {
  4932. done = 1;
  4933. break;
  4934. }
  4935. pset[pitchpos++] = nextpitch;
  4936. }
  4937. if(done)
  4938. break;
  4939. }
  4940. dz->bincnt = pitchpos; // Remember how many bins we have
  4941. } else { // is_elacs
  4942. arraysize = 0;
  4943. trueoct_cnt = 0;
  4944. semitone_len = 0;
  4945. while(trueoct_cnt < MIDIOCTSPAN) {
  4946. arraysize += scale_division;
  4947. semitone_len += pseudoct_size;
  4948. trueoct_cnt = (int)floor(semitone_len/SEMITONES_PER_OCTAVE);
  4949. }
  4950. if((dz->parray[QUANTPITCH] = (double *)malloc(arraysize * 4 * sizeof(double)))==NULL) {
  4951. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4952. return(MEMORY_ERROR);
  4953. }
  4954. pset = dz->parray[QUANTPITCH];
  4955. pitchpos = 0; // Dummy entry in position [0] - (allows pitchtop counter to tally with pitch centre conter)
  4956. // SPECIFY PITCHES IN EACH pseudo8va for all pseudo8vas until MIDIMAX is reached
  4957. thispitch = 0.0;
  4958. octfoot = 0.0;
  4959. while(thispitch <= MIDIMAX) {
  4960. for(n = 0;n < scale_division;n++) {
  4961. ratio = (double)n/(double)scale_division;
  4962. if((thispitch = (pseudoct_size * ratio) + octfoot) > MIDIMAX) {
  4963. break;
  4964. }
  4965. pset[pitchpos++] = thispitch;
  4966. }
  4967. octfoot += pseudoct_size;
  4968. }
  4969. dz->bincnt = pitchpos; // Remember how many bins we have
  4970. }
  4971. if(is_elacs || !flteq(fmod(reference_pitch,SEMITONES_PER_OCTAVE),0.0)) { // Either, is_elacs, so pitches not guaranteed to include reference_pitch
  4972. // OR, Reference-pitch is not at multiple of 12
  4973. // Find pitch closest to reference pitch, and find interval distance to ref-pitch
  4974. mindiff = HUGE;
  4975. mindiffat = 0;
  4976. for(n = 1; n < dz->bincnt; n++) { // pset[0] is a dummy
  4977. thisdiff = fabs(reference_pitch - pset[n]);
  4978. if(thisdiff < mindiff) {
  4979. mindiff = thisdiff;
  4980. mindiffat = n;
  4981. }
  4982. }
  4983. // Now transpose set so it includes ref-pitch
  4984. mindiff = reference_pitch - pset[mindiffat];
  4985. if(mindiff > 0.0) {
  4986. for(n = 1; n < dz->bincnt; n++) {
  4987. nupitch = pset[n] + mindiff;
  4988. if(nupitch > 127)
  4989. break;
  4990. pset[n] = nupitch;
  4991. }
  4992. dz->bincnt = n; // May be smaller than orig, if pset pushed eyond 127
  4993. } else if(mindiff < 0.0) {
  4994. nubincnt = 1;
  4995. for(n = 1; n < dz->bincnt; n++) {
  4996. nupitch = pset[n] + mindiff;
  4997. if(nupitch >= 0.0) // pset now below zero are ignored, so the new bincnt (m) does not increment
  4998. pset[nubincnt++] = nupitch; // Otherwise new pset are written over orig pset (possibly lower in array - but never higher!!)
  4999. }
  5000. dz->bincnt = nubincnt;
  5001. }
  5002. }
  5003. } else {
  5004. // If not scale: create array to store pitchdata initially read from file
  5005. if((dz->parray[PREPICH] = (double *)malloc((cntpitches + 1) * sizeof(double)))==NULL) {
  5006. sprintf(errstr,"INSUFFICIENT MEMORY to store Initial Filter Pitch Data.\n");
  5007. return(MEMORY_ERROR);
  5008. }
  5009. prepitch = dz->parray[PREPICH];
  5010. rewind(fp);
  5011. linecnt = 0;
  5012. cntpitches = 0;
  5013. while(fgets(temp,200,fp)!=NULL) {
  5014. p = temp;
  5015. while(isspace(*p))
  5016. p++;
  5017. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  5018. continue;
  5019. if(*p == '#')
  5020. continue;
  5021. while(get_float_from_within_string(&p,&dummy))
  5022. prepitch[cntpitches++] = dummy;
  5023. linecnt++;
  5024. }
  5025. fclose(fp);
  5026. if(is_thf) { // Sort each line of pitches & transpose into lowest octave
  5027. dz->quantcnt = entrycnt; // quantcnt isthe number of quantising pitches per line
  5028. dz->itemcnt = linecnt; // itemcnt is the number of different quantisation sets
  5029. sort_pitches_for_tvary_hf(dz->quantcnt,dz->itemcnt,dz);
  5030. dz->bincnt = (((entrycnt-1) * MIDIOCTSPAN) * dz->itemcnt) + dz->itemcnt;
  5031. // pitches dupl_vals for extra entry
  5032. // per in all every for time
  5033. // line 8vas line in each line
  5034. } else {
  5035. dz->itemcnt = cntpitches;
  5036. dz->itemcnt = sort_pitches(dz); // Some pitches may be duplicated: they also need to be in ascending order
  5037. if(is_hs) {
  5038. dz->quantcnt = dz->itemcnt; // Number of pitches to quantise to is exactly those entered
  5039. dz->bincnt = dz->itemcnt + 1; // Space for all entered pitches + dummy value at [0]
  5040. } else {
  5041. for(n = 0;n < dz->itemcnt; n++) { // For HF, duplicate pitches over all 8vas
  5042. while(prepitch[n] >= 0.0)
  5043. prepitch[n] -= SEMITONES_PER_OCTAVE; // 1st transpose all pitches into lowest octave
  5044. prepitch[n] += SEMITONES_PER_OCTAVE;
  5045. }
  5046. dz->itemcnt = sort_pitches(dz); // After transposition, some pitches may be duplicated
  5047. dz->bincnt = (dz->itemcnt * MIDIOCTSPAN) + 1; // pitches are to be duplicated in all 8vas + we need the dummy val at [0]
  5048. }
  5049. }
  5050. if((dz->parray[QUANTPITCH] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  5051. sprintf(errstr,"INSUFFICIENT MEMORY to store Quantisation pitch field.\n");
  5052. return(MEMORY_ERROR);
  5053. }
  5054. pset = dz->parray[QUANTPITCH];
  5055. if(is_hs) // For HS, merely copy pitches into final array
  5056. memcpy((char *)dz->parray[QUANTPITCH],(char *)dz->parray[PREPICH],dz->bincnt * sizeof(double));
  5057. else if(is_thf) { // For THF, copy pitches in each line-set into all 8vas in MIDI range
  5058. if((exit_status = octaviate_and_store_timed_hf_data(dz))<0)
  5059. return exit_status;
  5060. } else { // For HF, copy pitches into all 8vas in MIDI range
  5061. done = 0;
  5062. pitchpos = 0;
  5063. octstep = 0;
  5064. for(m=0;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  5065. for(n=0;n<dz->itemcnt;n++) { // Copy pitches in lowest octave into higher octaves
  5066. nextpitch = prepitch[n] + octstep;
  5067. if(nextpitch > MIDIMAX) {
  5068. done = 1;
  5069. break;
  5070. }
  5071. pset[pitchpos++] = nextpitch;
  5072. }
  5073. octstep += SEMITONES_PER_OCTAVE;
  5074. if(done)
  5075. break;
  5076. }
  5077. dz->quantcnt = pitchpos; // Remember how many bins we have
  5078. }
  5079. }
  5080. return FINISHED;
  5081. }
  5082. /****************************************** SORT_PITCHES ***************************/
  5083. int sort_pitches(dataptr dz)
  5084. {
  5085. int n, m;
  5086. double temp, *prepitch = dz->parray[PREPICH];
  5087. int len = dz->itemcnt;
  5088. for(n = 0; n < len - 1; n++) { // Sort into ascending order
  5089. for(m = n+1; m < len;m++) {
  5090. if(prepitch[m] < prepitch[n]) {
  5091. temp = prepitch[m];
  5092. prepitch[m] = prepitch[n];
  5093. prepitch[n] = temp;
  5094. }
  5095. }
  5096. }
  5097. for(n = 0; n < len-1; n++) { // Eliminate duplicates
  5098. if(flteq(prepitch[n+1],prepitch[n])) {
  5099. for(m = n+1;m < len;m++)
  5100. prepitch[m-1] = prepitch[m];
  5101. len--;
  5102. }
  5103. }
  5104. return len;
  5105. }
  5106. /****************************************** SORT_PITCHES_FOR_TVARY_HF ***************************/
  5107. int sort_pitches_for_tvary_hf(int entrycnt,int linecnt,dataptr dz)
  5108. {
  5109. int line, line_cnt, later_line_cnt, abs_cnt, later_abs_cnt;
  5110. double temp, *prepitch = dz->parray[PREPICH];
  5111. for(line = 0; line < linecnt; line++) { // For each line
  5112. for(line_cnt = 1, abs_cnt = line * entrycnt + 1; line_cnt < entrycnt - 1; line_cnt++,abs_cnt++) { // Ignoring the first (time) entry
  5113. for(later_line_cnt = line_cnt+1,later_abs_cnt = abs_cnt+1; later_line_cnt < entrycnt;later_line_cnt++,later_abs_cnt++) {
  5114. if(prepitch[later_abs_cnt] < prepitch[abs_cnt]) { // Sort pitches into ascending order
  5115. temp = prepitch[later_abs_cnt];
  5116. prepitch[later_abs_cnt] = prepitch[abs_cnt];
  5117. prepitch[abs_cnt] = temp;
  5118. }
  5119. }
  5120. }
  5121. for(line_cnt = 1, abs_cnt = line * entrycnt + 1; line_cnt < entrycnt; line_cnt++,abs_cnt++) { // transpose all pitches into lowest 8va
  5122. while(prepitch[abs_cnt] >= 0.0)
  5123. prepitch[abs_cnt] -= SEMITONES_PER_OCTAVE;
  5124. prepitch[abs_cnt] += SEMITONES_PER_OCTAVE;
  5125. }
  5126. }
  5127. return FINISHED;
  5128. }
  5129. /****************************************** FORMANTS_MAKEFILT ***************************/
  5130. int formants_makefilt(int inner_lpcnt,int *times_index,dataptr dz)
  5131. {
  5132. int exit_status, n, cc, vc, k, j, spstt, spend, ccstt, ccend, vcstt, peakloc, newcc, peakno, get_fundamental = 0;
  5133. float frqstt, frqend, thisamp, newfrq = 0.0;
  5134. double thispch, maxamp;
  5135. double *bintop = dz->parray[PBINTOP], *binamp = dz->parray[PBINAMP];
  5136. int *bincnt = dz->iparray[PCNTBIN], *peakat = dz->iparray[PEAKPOS];
  5137. int *ftimes = dz->lparray[FTIMES];
  5138. peakat += inner_lpcnt * PKBLOK;
  5139. if(*times_index < dz->timeblokcnt) { // If their is a list of times, and we haven't reached end of it
  5140. if(inner_lpcnt >= ftimes[*times_index]) { // If we've got to time-boundary for next filter
  5141. if((exit_status = build_filter(*times_index,dz)) < 0)
  5142. return(exit_status); // build the filter so far.
  5143. for(n = 0; n < dz->bincnt; n++) { // Then zero the counting and amplitude sum bins for the next block of windows
  5144. bincnt[n] = 0;
  5145. binamp[n] = 0.0;
  5146. }
  5147. (*times_index)++;
  5148. }
  5149. }
  5150. for(n = 0; n < PKBLOK-1; n+=2) { // Going through the trofs in pairs
  5151. peakno = n/2;
  5152. if(dz->fundamental && n == 0)
  5153. get_fundamental = 1;
  5154. spstt = peakat[n]; // Get specenvamp locations of 2 adjacent trofs.
  5155. spend = peakat[n+2];
  5156. frqstt = dz->specenvtop[spstt]; // Find freq of top frq-edge of lower trof
  5157. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  5158. frqend = dz->specenvtop[spend-1]; // Find freq of bottom frq-edge of upper trof
  5159. ccend = (int)ceil(frqend/dz->chwidth);
  5160. maxamp = -HUGE; // Find the flbuptr location of maximum amplitude.
  5161. vcstt = ccstt * 2;
  5162. peakloc = ccstt;
  5163. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  5164. if(dz->flbufptr[0][AMPP] > maxamp) {
  5165. maxamp = dz->flbufptr[0][AMPP];
  5166. peakloc = cc;
  5167. }
  5168. }
  5169. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  5170. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  5171. return exit_status;
  5172. if(newfrq > 0.0) // i.e. if we really have pitch data here
  5173. peakloc = newcc;
  5174. get_fundamental = 0; // Only (try to) get fundamental when in first formant
  5175. }
  5176. vc = peakloc;
  5177. thisamp = dz->flbufptr[0][AMPP];
  5178. thispch = unchecked_hztomidi((double)dz->flbufptr[0][FREQ]);
  5179. if(thispch > 0 && thispch <= 127) {
  5180. for(k = 1,j= (peakno*dz->bincnt)+1;k < dz->bincnt;k++,j++) { // Find which bin (if any) the pitch falls in
  5181. if(thispch < bintop[k] && thispch > bintop[k-1]) {
  5182. bincnt[j]++; // Count occurences of this pitch
  5183. binamp[j] += thisamp; // Sum amps of all occurences of this pitch
  5184. break;
  5185. }
  5186. }
  5187. }
  5188. }
  5189. return FINISHED;
  5190. }
  5191. /****************************************** BUILD_FILTER ***************************/
  5192. int build_filter(int times_index,dataptr dz)
  5193. {
  5194. int n, j, k, z, pch, amp, filtercnt, this_time, next_time, target, get_below = 0, pitchcnt, newpitch, filtlinelen;
  5195. int maxcnt;
  5196. double maxfiltamp = 0.0, maxamp = 0.0, starttime, endtime, lasttime = 0.0, tempval, minpitch;
  5197. double *binpitch = dz->parray[PBINPCH], *binamp = dz->parray[PBINAMP];
  5198. double *filtpch = dz->parray[LOCALPCH], *filtamp = dz->parray[LOCALAMP];
  5199. double *pchstore = dz->parray[FILTPICH], *ampstore = dz->parray[FILTAMP];
  5200. double *fpitches = dz->parray[FPITCHES];
  5201. float *filtline, *lastfiltline;
  5202. double lastpch;
  5203. int *countbin = dz->iparray[PCNTBIN];
  5204. int maxat = 0, maxats[MAXFILTVALS];
  5205. int *ftimes = dz->lparray[FTIMES];
  5206. int blokcnt = dz->iparam[FPKCNT] * 4;
  5207. int storepos = (times_index - 1) * blokcnt, storecnt;
  5208. int filtbas, fmntno, fcnt, do_intermediate_line;
  5209. memset((char *)filtpch,0,dz->iparam[FPKCNT] * 4 * sizeof(int));
  5210. memset((char *)filtamp,0,dz->iparam[FPKCNT] * 4 * sizeof(double));
  5211. if(dz->param[FBELOW])
  5212. get_below = 1;
  5213. // FIND MOST PROMINENT PITCHES IN THIS BLOK
  5214. for(fmntno = 0;fmntno < 4;fmntno++) {
  5215. minpitch = 2000;
  5216. filtbas = (fmntno * dz->iparam[FPKCNT]);
  5217. memset((char *)maxats,0,MAXFILTVALS * sizeof(int));
  5218. for(fcnt = 0,filtercnt = filtbas; fcnt < dz->iparam[FPKCNT]; fcnt++,filtercnt++) {
  5219. maxcnt = -1;
  5220. maxat = 0;
  5221. for(j = 1,k = (fmntno*dz->bincnt)+1;j< dz->bincnt;j++,k++) {
  5222. if(countbin[k] > maxcnt) {
  5223. maxcnt = countbin[k]; // Find pitch that occurs most frequently
  5224. maxamp = binamp[k];
  5225. maxat = k;
  5226. } else if(countbin[k] == maxcnt) {
  5227. if(binamp[k] > maxamp) { // If more than 1 pitch is equally frequent
  5228. maxamp = binamp[k]; // Take the one with the greatest amplitude (summed over all occurences)
  5229. maxat = k;
  5230. }
  5231. }
  5232. }
  5233. maxats[fcnt] = maxat;
  5234. filtpch[filtercnt] = binpitch[maxat]; // Set pitch found as a filter pitch
  5235. filtamp[filtercnt] = binamp[maxat];
  5236. countbin[maxat] = 0; // Eliminate this pitch from next search
  5237. minpitch = min(filtpch[filtercnt],minpitch);
  5238. // Freqs Below a given pitch are required, search for
  5239. if(get_below && (minpitch > dz->param[FBELOW])) {
  5240. while(minpitch > dz->param[FBELOW]) {
  5241. target = min(fcnt,dz->iparam[FPKCNT] - 1);
  5242. target += filtbas;
  5243. maxcnt = -1;
  5244. maxat = 0;
  5245. for(j = 1, k = (fmntno * dz->bincnt)+1;j < dz->bincnt;j++,k++) {
  5246. if(countbin[k] > maxcnt) {
  5247. maxcnt = countbin[k]; // Find pitch that occurs most frequently
  5248. maxamp = binamp[k];
  5249. maxat = k;
  5250. } else if(countbin[k] == maxcnt) {
  5251. if(binamp[k] > maxamp) { // If more than 1 pitch is equally frequent
  5252. maxamp = binamp[k]; // Take the one with the greatest amplitude (summed over all occurences)
  5253. maxat = k;
  5254. }
  5255. }
  5256. }
  5257. if(maxcnt <= 0) // IF there are NO suitable low frqs, exit
  5258. break;
  5259. if(binpitch[maxat] < minpitch) {
  5260. filtpch[target] = binpitch[maxat]; // Set pitch found as last filter pitch
  5261. filtamp[target] = binamp[maxat];
  5262. minpitch = binpitch[maxat]; // will; break from loop
  5263. }
  5264. countbin[maxat] = 0; // Eliminate this pitch from next search
  5265. }
  5266. }
  5267. if(maxcnt > 0) // Found minimum, drop searching in other formants
  5268. get_below = 0;
  5269. }
  5270. }
  5271. // SORT INTO ASCENDING PITCH ORDER AND SILENCE DUPLICATES
  5272. for(n = 0; n < blokcnt - 1; n++) {
  5273. for(k = n+1; k < blokcnt; k++) {
  5274. if(filtpch[n] > filtpch[k]) {
  5275. tempval = filtpch[n];
  5276. filtpch[n] = filtpch[k];
  5277. filtpch[k] = tempval;
  5278. tempval = filtamp[n];
  5279. filtamp[n] = filtamp[k];
  5280. filtamp[k] = tempval;
  5281. } else if(flteq(filtpch[n],filtpch[k])) {
  5282. filtamp[k] = 0.0;
  5283. }
  5284. }
  5285. }
  5286. // IF AMPS TO BE RETAINED, FIND MAX, IN ORDER TO NORMALISE
  5287. for(filtercnt = 0; filtercnt < blokcnt; filtercnt++) {
  5288. if(dz->vflag[KEEPAMP])
  5289. maxfiltamp = max(maxfiltamp,filtamp[filtercnt]);
  5290. else if(dz->vflag[KEEPINV]) { // If amps to be inverted, invert them
  5291. if(!flteq(filtamp[filtercnt],0.0))
  5292. filtamp[filtercnt] = 1.0/filtamp[filtercnt];
  5293. maxfiltamp = max(maxfiltamp,filtamp[filtercnt]);
  5294. } else // Otherwise, set all amps to 1
  5295. filtamp[filtercnt] = 1.0;
  5296. }
  5297. if(dz->vflag[KEEPAMP] || dz->vflag[KEEPINV]) { // If amps or invamps retained, normalise
  5298. for(filtercnt = 0; filtercnt < blokcnt; filtercnt++)
  5299. filtamp[filtercnt] /= maxfiltamp;
  5300. }
  5301. // STORE THE FILTER DATA
  5302. for(filtercnt = 0, storecnt = storepos; filtercnt < blokcnt; filtercnt++,storecnt++) {
  5303. pchstore[storecnt] = filtpch[filtercnt];
  5304. ampstore[storecnt] = filtamp[filtercnt];
  5305. }
  5306. // ONCE ALL FILTER DATA GENERATED:
  5307. if(times_index >= dz->timeblokcnt) {
  5308. // FIND 1st DISTINCT PITCH USED
  5309. pitchcnt = 0;
  5310. for(n = 0; n < storecnt; n++) {
  5311. if(ampstore[n] > 0.0) {
  5312. fpitches[0] = pchstore[n];
  5313. pitchcnt++;
  5314. break;
  5315. }
  5316. }
  5317. if(pitchcnt == 0) {
  5318. sprintf(errstr,"NO VALID PITCHES FOUND IN FILTER DATA.\n");
  5319. return DATA_ERROR;
  5320. }
  5321. // FIND ALL DISTINCT PITCHES USED
  5322. while(n < storecnt) {
  5323. if(ampstore[n] > 0.0) {
  5324. newpitch = 1;
  5325. for(k = 0; k < pitchcnt;k++) {
  5326. if(flteq(pchstore[n],pchstore[k])) {
  5327. newpitch = 0;
  5328. break;
  5329. }
  5330. }
  5331. if(newpitch)
  5332. fpitches[pitchcnt++] = pchstore[n];
  5333. }
  5334. n++;
  5335. }
  5336. // SORT DISTINCT PITCHES INTO ASCENDING ORDER && ELIMINATE DUPLICATES
  5337. for(n = 0; n < pitchcnt - 1; n++) {
  5338. for(k = n+1; k < pitchcnt; k++) {
  5339. if(fpitches[n] > fpitches[k]) {
  5340. tempval = fpitches[n];
  5341. fpitches[n] = fpitches[k];
  5342. fpitches[k] = tempval;
  5343. } else if(flteq(fpitches[n],fpitches[k])) {
  5344. if(k < pitchcnt - 1) {
  5345. for(j = k+1;j < pitchcnt;j++)
  5346. fpitches[j-1] = fpitches[j];
  5347. }
  5348. pitchcnt--;
  5349. k--;
  5350. }
  5351. }
  5352. }
  5353. /* TEST *
  5354. for(z = 0;z < pitchcnt;z++)
  5355. fprintf(stderr,"%.1lf ",fpitches[z]);
  5356. fprintf(stderr,"\n");
  5357. /* TEST */
  5358. // ELIMINATE ANY PITCH ZEROS FROM PITCHES TO BE USED IN FILTER
  5359. for(n = 0; n < pitchcnt; n++) {
  5360. if(fpitches[n] <= 0.0) {
  5361. if(n < pitchcnt - 1) {
  5362. for(k = n+1;k < pitchcnt;k++)
  5363. fpitches[k-1] = fpitches[k];
  5364. }
  5365. pitchcnt--;
  5366. }
  5367. }
  5368. filtlinelen = (pitchcnt * 2)+1;
  5369. if((dz->fptr[FILTLINE] = (float *)malloc(filtlinelen * sizeof(float)))==NULL) {
  5370. sprintf(errstr,"INSUFFICIENT MEMORY to store varibank filter line-entry data.\n");
  5371. return(MEMORY_ERROR);
  5372. }
  5373. if((dz->fptr[LASTFLINE] = (float *)malloc(filtlinelen * sizeof(float)))==NULL) {
  5374. sprintf(errstr,"INSUFFICIENT MEMORY to store varibank filter line-entry data.\n");
  5375. return(MEMORY_ERROR);
  5376. }
  5377. filtline = dz->fptr[FILTLINE];
  5378. lastfiltline = dz->fptr[LASTFLINE];
  5379. // OUTPUT THE FILTER
  5380. for(this_time = 0,next_time = 1; this_time < dz->timeblokcnt; this_time++,next_time++) {
  5381. starttime = ftimes[this_time] * dz->frametime;
  5382. endtime = ftimes[next_time] * dz->frametime; // There are (say) 5 times and 4 stores
  5383. storepos = this_time * blokcnt;
  5384. filtline[0] = (float)starttime;
  5385. for(z = 0,pch = 1,amp = 2;z < pitchcnt;z++,pch+=2,amp+=2) {
  5386. filtline[pch] = (float)fpitches[z];
  5387. filtline[amp] = 0.0; // Establish a zero-amp line for filter
  5388. }
  5389. for(n = 0,k = storepos; n < filtercnt; n++,k++) {
  5390. if(pchstore[k] <= 0.0) { // Interpolate through any pitch-zeros
  5391. j = storepos;
  5392. lastpch = pchstore[k];
  5393. while(lastpch <= 0.0) {
  5394. j -= blokcnt;
  5395. if(j < 0)
  5396. break;
  5397. lastpch = pchstore[j];
  5398. }
  5399. while(lastpch <= 0.0) {
  5400. j += blokcnt;
  5401. if(j > dz->iparam[FPKCNT] * 4 * dz->timeblokcnt)
  5402. break;
  5403. lastpch = pchstore[j];
  5404. }
  5405. if(lastpch <= 0.0)
  5406. pchstore[k] = -1.0; // If truly a zero (i.e. at no time is this pitch NOT a zero) mark as such
  5407. else
  5408. pchstore[k] = lastpch;
  5409. }
  5410. for(pch = 1,amp=2;pch < filtlinelen;pch+=2,amp+=2) { // For each pitch used at this time
  5411. if(pchstore[k] == filtline[pch]) { // Activate this pitch (turn on amp) in the filter
  5412. filtline[amp] = (float)ampstore[k];
  5413. break;
  5414. }
  5415. }
  5416. }
  5417. if(this_time > 0) {
  5418. do_intermediate_line = 0;
  5419. for(pch = 1,amp = 2;pch < filtlinelen;pch+=2,amp+=2) {
  5420. if(filtline[amp] != lastfiltline[amp]) { // If the amplitude of any pitch in filter changes
  5421. do_intermediate_line = 1;
  5422. break;
  5423. }
  5424. }
  5425. if(do_intermediate_line) { // Output an intermediate line, half-way between this time and last-time
  5426. fprintf(dz->fp,"%lf ",(lasttime + starttime)/2.0);
  5427. for(z=1; z < filtlinelen;z++) // With the values from the previous time,
  5428. fprintf(dz->fp,"%lf ",lastfiltline[z]); // So that an amplitude fade or rise will happen in 1/2 duration of previous block
  5429. fprintf(dz->fp,"\n");
  5430. }
  5431. }
  5432. for(z=0; z < filtlinelen;z++) // Output the filter line at this time
  5433. fprintf(dz->fp,"%lf ",filtline[z]);
  5434. fprintf(dz->fp,"\n");
  5435. // Remember this line, in case we need to construct intermediate line
  5436. memcpy((char *)lastfiltline,(char *)filtline,filtlinelen * sizeof(float));
  5437. lasttime = starttime;
  5438. }
  5439. }
  5440. return FINISHED;
  5441. }
  5442. /**************************** FIND_FUNDAMENTAL *************************/
  5443. int find_fundamental(float thisfrq,double target,int peakcc,float *newfrq,dataptr dz)
  5444. {
  5445. int cc, vc, fund_at = -1, divisor = 2;
  5446. double goalfrq, maxamp = -HUGE;
  5447. float foundfrq = thisfrq;
  5448. if(target == 0.0)
  5449. target = thisfrq/* /2 */;
  5450. while(fund_at < 0) {
  5451. goalfrq = thisfrq/(double)divisor;
  5452. if(goalfrq < target * TWO_OVER_THREE)
  5453. break;
  5454. for(cc=0,vc=0;cc < peakcc;cc++,vc+=2) {
  5455. if(equivalent_pitches(dz->flbufptr[0][FREQ],goalfrq,dz) && dz->flbufptr[0][AMPP] > maxamp) {
  5456. maxamp = dz->flbufptr[0][AMPP];
  5457. foundfrq = dz->flbufptr[0][FREQ];
  5458. fund_at = cc;
  5459. }
  5460. }
  5461. if(fund_at < 0)
  5462. divisor++;
  5463. }
  5464. *newfrq = foundfrq; // If no new frq found, newfrq defaults to input frq
  5465. if(fund_at >= 0)
  5466. return fund_at;
  5467. return peakcc; // If no new frq found, new chan defaults to original chan
  5468. }
  5469. /**************************** EQUIVALENT_PITCHES *************************/
  5470. int equivalent_pitches(double frq1, double frq2, dataptr dz)
  5471. {
  5472. double ratio;
  5473. int iratio;
  5474. double intvl;
  5475. ratio = frq1/frq2;
  5476. iratio = round(ratio);
  5477. if(iratio!=1)
  5478. return(FALSE);
  5479. if(ratio > iratio)
  5480. intvl = ratio/(double)iratio;
  5481. else
  5482. intvl = (double)iratio/ratio;
  5483. if(intvl > dz->in_tune)
  5484. return FALSE;
  5485. return TRUE;
  5486. }
  5487. /**************************** FORMANTS_MOVE *************************/
  5488. int formants_move(int inner_lpcnt,dataptr dz)
  5489. {
  5490. int exit_status, truecnt, fno, paramno = 0, lotrofchan = 0, peakchan = 0, hitrofchan = 0, cc, vc, top_hno;
  5491. float lotrofamp = 0.0, peakamp = 0.0, hitrofamp = 0.0, the_fundamental = 0.0, frq;
  5492. double frqoffset, pre_amptotal = 0.0, post_amptotal = 0.0;
  5493. float *peaktrof = dz->fptr[PKTROF];
  5494. int *pos = dz->iparray[PEAKPOS];
  5495. pos += inner_lpcnt * PKBLOK;
  5496. peaktrof += inner_lpcnt * PKBLOK;
  5497. if(dz->fundamental)
  5498. the_fundamental = dz->pitches[inner_lpcnt];
  5499. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  5500. return(exit_status);
  5501. if(dz->xclude_nonh || dz->vflag[SQZ_KHM]) {
  5502. top_hno = 0;
  5503. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  5504. frq = dz->flbufptr[0][FREQ];
  5505. if(dz->xclude_nonh) { // If excluding non-harmonic data
  5506. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  5507. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  5508. continue; // zero it
  5509. }
  5510. } else if(dz->vflag[SQZ_KHM]) { // If suppressing harmonics
  5511. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  5512. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  5513. dz->flbufptr[0][AMPP] = 0.0f;
  5514. continue;
  5515. }
  5516. }
  5517. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  5518. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  5519. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  5520. continue;
  5521. }
  5522. }
  5523. }
  5524. for(fno = 1;fno <= 4; fno++) {
  5525. truecnt = 0;
  5526. switch(fno) {
  5527. case(1):
  5528. paramno = FMOVE1;
  5529. lotrofchan = pos[0];
  5530. peakchan = pos[1];
  5531. hitrofchan = pos[2];
  5532. lotrofamp = peaktrof[0];
  5533. peakamp = peaktrof[1];
  5534. hitrofamp = peaktrof[2];
  5535. break;
  5536. case(2):
  5537. paramno = FMOVE2;
  5538. lotrofchan = pos[2];
  5539. peakchan = pos[3];
  5540. hitrofchan = pos[4];
  5541. lotrofamp = peaktrof[2];
  5542. peakamp = peaktrof[3];
  5543. hitrofamp = peaktrof[4];
  5544. break;
  5545. case(3):
  5546. paramno = FMOVE3;
  5547. lotrofchan = pos[4];
  5548. peakchan = pos[5];
  5549. hitrofchan = pos[6];
  5550. lotrofamp = peaktrof[4];
  5551. peakamp = peaktrof[5];
  5552. hitrofamp = peaktrof[6];
  5553. break;
  5554. case(4):
  5555. paramno = FMOVE4;
  5556. lotrofchan = pos[6];
  5557. peakchan = pos[7];
  5558. hitrofchan = pos[8];
  5559. lotrofamp = peaktrof[6];
  5560. peakamp = peaktrof[7];
  5561. hitrofamp = peaktrof[8];
  5562. break;
  5563. }
  5564. frqoffset = dz->param[paramno]; // Read appropriate parameter for frq offset of the formant
  5565. if(frqoffset != 0.0) {
  5566. if((exit_status = move_formant(fno,frqoffset,lotrofchan,peakchan,hitrofchan,lotrofamp,peakamp,hitrofamp,&truecnt,dz))<0)
  5567. return exit_status;
  5568. dz->iparray[FCNT][fno] = truecnt;
  5569. }
  5570. }
  5571. if((exit_status = concatenate_moved_formants(dz))<0)
  5572. return exit_status;
  5573. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  5574. return(exit_status);
  5575. if(post_amptotal > pre_amptotal) {
  5576. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  5577. return(exit_status);
  5578. }
  5579. if(dz->param[FMVGAIN] > 0.0 && !flteq(dz->param[FMVGAIN],1.0)) {
  5580. for(vc=0;vc<dz->wanted;vc+=2)
  5581. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FMVGAIN]);
  5582. }
  5583. return FINISHED;
  5584. }
  5585. /**************************** MOVE_FORMANT *************************/
  5586. int move_formant(int fno,double frqoffset,int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp,float hitrofamp,int *truecnt,dataptr dz)
  5587. {
  5588. int exit_status, n, speccnt, chanwidth, is_narrowedabove = 0, is_narrowedbelow = 0;
  5589. float *thisamp = NULL, *thisfrq = NULL, *thispch = NULL;
  5590. double frqcentre, half_specbandwidth, frqstep = 0.0,frqstart = 0.0;
  5591. switch(fno) {
  5592. case(1): thisamp = dz->fptr[FAMP1]; thisfrq = dz->fptr[FFRQ1], thispch = dz->fptr[FPCH1]; break;
  5593. case(2): thisamp = dz->fptr[FAMP2]; thisfrq = dz->fptr[FFRQ2], thispch = dz->fptr[FPCH2]; break;
  5594. case(3): thisamp = dz->fptr[FAMP3]; thisfrq = dz->fptr[FFRQ3], thispch = dz->fptr[FPCH3]; break;
  5595. case(4): thisamp = dz->fptr[FAMP4]; thisfrq = dz->fptr[FFRQ4], thispch = dz->fptr[FPCH4]; break;
  5596. }
  5597. for(n=0;n<dz->specenvcnt;n++) // Flag all new formant data as "unknown"
  5598. thisamp[n] = -1.0;
  5599. speccnt = 0;
  5600. *truecnt = 0; // When formant set to specific frq, Must create bandwidth related to bwidth of (moved) formant
  5601. if(dz->mode == F_MOVE2) { // Use measure of half specenvelope bandwidth
  5602. frqcentre = frqoffset; // CHWIDTH 1 2 3 4 5
  5603. half_specbandwidth = dz->frq_step/2.0; // = bwidth | | | | | | | | | | | | | | |
  5604. chanwidth = (hitrofchan - lotrofchan) + 1; // bwidth --- ------ --------- ------------ ---------------
  5605. if(!dz->vflag[MOV2_NRW]) { // -0.5bw -1bw -1.5bw -2bw -2.5bw
  5606. frqstart = max(0.0,frqcentre - (half_specbandwidth * chanwidth));// Band edge below centre frq This = 1/2chwidth * bwidth = chwidth * 1/2bwidth
  5607. frqstep = dz->frq_step;
  5608. } else {
  5609. frqstart = max(0.0,frqcentre - half_specbandwidth); // Narrow bands use a single bandwidth and slice it
  5610. frqstep = dz->frq_step/(double)chanwidth;
  5611. }
  5612. }
  5613. for(n=lotrofchan;n <= hitrofchan;n++) {
  5614. switch(dz->mode) {
  5615. case(F_MOVE):
  5616. thisfrq[speccnt] = (float)(dz->specenvfrq[n] + frqoffset); // Move the frq positions of the specenv information
  5617. break;
  5618. case(F_MOVE2):
  5619. thisfrq[speccnt] = (float)frqstart; // Reset the frq position of the specenv information
  5620. frqstart += frqstep;
  5621. frqstart = min(frqstart,F_HIFRQ_LIMIT);
  5622. break;
  5623. }
  5624. thisamp[speccnt] = dz->specenvamp[n];
  5625. if(thisfrq[speccnt] < F_LOFRQ_LIMIT) // If anything drops off bottom of range, keep it but DON'T count it (it then gets overwritten), but note this
  5626. is_narrowedbelow = 1; // (And don't attemp to calc pitch if frq falls below 0.0)
  5627. else {
  5628. thispch[speccnt] = (float)log10(thisfrq[speccnt]); // Calc pitch at thus frq
  5629. if(thisfrq[speccnt] > F_HIFRQ_LIMIT) // If anything drops off top of range, note this, keep it and COUNT it
  5630. is_narrowedabove = 1;
  5631. else
  5632. (*truecnt)++; // Count the number of chans which are within range
  5633. }
  5634. speccnt++; // Count the number of channels processed
  5635. }
  5636. if(*truecnt == 0) // i.e. everything is now out of range, so formant contributes nothing to output
  5637. return FINISHED;
  5638. if(is_narrowedbelow) {
  5639. if((exit_status = edgefade_formant(thisfrq,thisamp,thispch, 0, truecnt,lotrofchan,peakchan,hitrofchan,lotrofamp,peakamp,hitrofamp,(float)F_LOFRQ_LIMIT,dz))>0)
  5640. return exit_status; // below,chansused original-trof-peak-trof & their orig amps frqlimit
  5641. } else if(is_narrowedabove) {
  5642. if((exit_status = edgefade_formant(thisfrq,thisamp,thispch, 1, truecnt,lotrofchan,peakchan,hitrofchan,lotrofamp,peakamp,hitrofamp,(float)F_HIFRQ_LIMIT,dz))>0)
  5643. return exit_status; // above,chansused original-trof-peak-trof & their orig amps frqlimit
  5644. }
  5645. return FINISHED;
  5646. }
  5647. /*********************************************** CONCATENATE_MOVED_FORMANTS *****************************************/
  5648. int concatenate_moved_formants(dataptr dz)
  5649. {
  5650. int exit_status, cc, vc, fmnt, startbad = 0, midbad = 0, badstt = 0, k, kk, j ,jj;
  5651. float frq;
  5652. double maxamp, amp, thisspecamp1, valgap, ratio, diff, startval;
  5653. double *spec3_amp = dz->parray[FSPEC3];
  5654. double *multbuf = dz->parray[FMULT];
  5655. float *spec3amps[5], *spec3pchs[5];
  5656. int truecnt[5];
  5657. spec3amps[1] = dz->fptr[FAMP1];
  5658. spec3amps[2] = dz->fptr[FAMP2];
  5659. spec3amps[3] = dz->fptr[FAMP3];
  5660. spec3amps[4] = dz->fptr[FAMP4];
  5661. spec3pchs[1] = dz->fptr[FPCH1];
  5662. spec3pchs[2] = dz->fptr[FPCH2];
  5663. spec3pchs[3] = dz->fptr[FPCH3];
  5664. spec3pchs[4] = dz->fptr[FPCH4];
  5665. truecnt[1] = dz->iparray[FCNT][1];
  5666. truecnt[2] = dz->iparray[FCNT][2];
  5667. truecnt[3] = dz->iparray[FCNT][3];
  5668. truecnt[4] = dz->iparray[FCNT][4];
  5669. if(!(truecnt[1] || truecnt[2] || truecnt[3] || truecnt[4]))
  5670. return FINISHED;
  5671. else
  5672. dz->ischange = 1;
  5673. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc += 2) {
  5674. frq = dz->flbufptr[0][FREQ]; // For the frq at this flbufptr channel
  5675. maxamp = -HUGE;
  5676. for(fmnt = 1; fmnt <= 4; fmnt++) { // Find the largest formant env value in the 4 formant arrays
  5677. getspecenv3amp(frq,&amp,spec3pchs[fmnt],spec3amps[fmnt],truecnt[fmnt],dz);
  5678. maxamp = max(amp,maxamp);
  5679. }
  5680. spec3_amp[cc] = (float)maxamp;
  5681. if(maxamp < 0.0) { // No formant data found
  5682. if(frq > F_HIFRQ_LIMIT)
  5683. multbuf[cc] = 1.0; // For frq range of source above upper frq limit, no change to source
  5684. else
  5685. multbuf[cc] = -1.0; // Otherwise flag that we have no new formant data at this frq (should already be -1 by default)
  5686. } else {
  5687. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5688. return(exit_status); // Find original formant envelope value
  5689. if(thisspecamp1 <= 0.0)
  5690. multbuf[cc] = 0.0;
  5691. else
  5692. multbuf[cc] = maxamp/thisspecamp1; // Change in relation to new specenv value
  5693. }
  5694. }
  5695. startbad = 0; // Now smooth the new formant data curve
  5696. midbad = 0;
  5697. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  5698. if(multbuf[cc] < 0.0) {
  5699. switch(cc) {
  5700. case(0):
  5701. startbad++;
  5702. break;
  5703. default:
  5704. if(startbad)
  5705. startbad++;
  5706. else {
  5707. if(midbad == 0) {
  5708. badstt = cc;
  5709. }
  5710. midbad++;
  5711. }
  5712. break;
  5713. }
  5714. } else {
  5715. if(startbad) { // If no formant info at start
  5716. for(k = 0,kk = (k*2)+1;k < startbad;k++,kk+=2) { // force these envelope vals to take same level as 1st trof
  5717. if(multbuf[cc] == 1.0) // No formant data found in window, maxamp = 0.0
  5718. spec3_amp[k] = 0.0;
  5719. else
  5720. spec3_amp[k] = spec3_amp[cc];
  5721. frq = dz->flbufptr[0][kk];
  5722. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5723. return(exit_status);
  5724. if(thisspecamp1 <= 0.0)
  5725. multbuf[k] = 0.0;
  5726. else
  5727. multbuf[k] = spec3_amp[k]/thisspecamp1; // Change in relation to new (interpolated) specenv value
  5728. }
  5729. startbad = 0;
  5730. } else if(midbad) { // IF no formant info within, interpolate between trofs on either side
  5731. if(multbuf[badstt-1] == 1.0) // No formant data found in window, maxamp = 0.0
  5732. startval = 0.0;
  5733. else
  5734. startval = spec3_amp[badstt-1];
  5735. if(multbuf[cc] == 1.0) // No formant data found in window, maxamp = 0.0: gap = 0.0 - startval
  5736. valgap = -startval;
  5737. else
  5738. valgap = spec3_amp[cc] - startval;
  5739. for(k = 0,j = badstt,jj = (badstt*2)+1; k < midbad;k++,j++,jj+=2) {
  5740. ratio = (double)(k+1)/(double)(midbad+1);
  5741. diff = valgap * ratio;
  5742. spec3_amp[j] = (float)(startval + diff);
  5743. frq = dz->flbufptr[0][jj];
  5744. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5745. return(exit_status);
  5746. if(thisspecamp1 <= 0.0)
  5747. multbuf[j] = 0.0;
  5748. else
  5749. multbuf[j] = spec3_amp[j]/thisspecamp1; // Change in relation to new specenv value
  5750. }
  5751. midbad = 0;
  5752. }
  5753. }
  5754. }
  5755. if(midbad) { // If no formant info at end, force endvals to have same val as trof at end of last formant
  5756. startval = spec3_amp[badstt-1];
  5757. for(cc = badstt, vc = cc*2; cc < dz->clength;cc++,vc+=2) {
  5758. frq = dz->flbufptr[0][FREQ];
  5759. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5760. return(exit_status);
  5761. if(thisspecamp1 <= 0.0)
  5762. multbuf[cc] = 0.0;
  5763. else
  5764. multbuf[cc] = startval/thisspecamp1; // Change in relation to new specenv value
  5765. }
  5766. }
  5767. if(dz->vflag[MOV_ZEROTOP]) { // If top of spectrum (above top formant) to be zeroed
  5768. for(cc = dz->clength - 1;cc >= 0;cc--) { // Search down multbuf whilst ever the multiplier value is 1.0
  5769. if(multbuf[cc] == 1.0) // i.e. multbuf does nothing to the spectrum i.e. no formant data has been moved there.
  5770. multbuf[cc] = 0.0; // and zero this not-reformanted area of the spectrum
  5771. else
  5772. break;
  5773. }
  5774. }
  5775. // Now do the formant transformation!!
  5776. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc += 2)
  5777. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * multbuf[cc]);
  5778. return FINISHED;
  5779. }
  5780. /**************************** EDGEFADE_FORMANT *************************/
  5781. int edgefade_formant(float *thisfrq,float *thisamp,float *thispch,int hi,
  5782. int *nuchanlen, int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp, float hitrofamp,float frqlimit,dataptr dz)
  5783. {
  5784. int chanlen, preskirtlen, nupreskirtlen, n, origchanlo, origchanhi;
  5785. double shrinkage, trofrise, fracpos, peakampfoot, peakfracpos, peakamprise, nupeakamprise;
  5786. double nupeakamp, envfoot, origchan, diff, amp, amprise, newamprise, newamp, origchfrac;
  5787. float origamplo, origamphi;
  5788. if(*nuchanlen > 1) {
  5789. chanlen = hitrofchan - lotrofchan; // No of channels originally spanned by formant
  5790. shrinkage = (double)(*nuchanlen)/(double)chanlen; // Shrinkage of formant-size
  5791. preskirtlen = peakchan - lotrofchan; // channel-length of rising skirt to original peak
  5792. trofrise = hitrofamp - lotrofamp; // Change in level between the 2 trofs bracketing the peak
  5793. peakfracpos = (double)preskirtlen/(double)chanlen; // Fractional position of peak between trofs
  5794. peakampfoot = lotrofamp + (trofrise * peakfracpos); // "Foot" of peak lies on the line joining the 2 bracketing trofs
  5795. peakamprise = peakamp - peakampfoot; // "Rise" is height of peak above foot
  5796. nupeakamprise = peakamprise * shrinkage; // Peak height lowered porportionally to shrinkage of format width
  5797. nupeakamp = peakampfoot + nupeakamprise;
  5798. nupreskirtlen = (int)round((double)preskirtlen * shrinkage);// Rising skirt of peak shrunk in size
  5799. for(n = 0; n < nupreskirtlen; n++) { // For each channel in the new preskirt
  5800. fracpos = (double)n/(double)(*nuchanlen);
  5801. envfoot = (trofrise * fracpos) + lotrofamp; // Calculate the value of the trof-line (interp value beween the 2 bracketing trofs)
  5802. origchan = (double)lotrofchan + ((double)chanlen * fracpos);// Which channel-position in ORIG specenv corresponds to this fraction into the skirt
  5803. origchanlo = (int)floor(origchan); // Find the bracketing channels in ORIG specenv
  5804. origchanhi = min(origchanlo+1,dz->specenvcnt-1);
  5805. origchfrac = origchan - (double)origchanlo;
  5806. origamplo = dz->specenvamp[origchanlo];
  5807. origamphi = dz->specenvamp[origchanhi];
  5808. diff = origamphi - origamplo;
  5809. amp = origamplo + (origchfrac * diff); // Use these to interpolate for a value from ORIG specenvamp
  5810. amprise = amp - envfoot; // How far is this level above the trof-line
  5811. newamprise = amprise * shrinkage; // Shrink this rise-above-trof
  5812. newamp = envfoot + newamprise; // and calculate the new env amplitude.
  5813. thisamp[n] = (float)newamp; // store it
  5814. }
  5815. thisamp[n] = (float)nupeakamp; // Set peak to new (shrunk) level
  5816. for(n = nupreskirtlen + 1; n < *nuchanlen; n++) { // Do simil calcs for the post-skirt
  5817. fracpos = (double)n/(double)(*nuchanlen);
  5818. envfoot = (trofrise * fracpos) + lotrofamp;
  5819. origchan = (double)lotrofchan + ((double)chanlen * fracpos);
  5820. origchanlo = (int)floor(origchan);
  5821. origchanhi = min(origchanlo+1,dz->specenvcnt-1);
  5822. origchfrac = origchan - (double)origchanlo;
  5823. origamplo = dz->specenvamp[origchanlo];
  5824. origamphi = dz->specenvamp[origchanhi];
  5825. diff = origamphi - origamplo;
  5826. amp = origamplo + (origchfrac * diff);
  5827. amprise = amp - envfoot;
  5828. newamprise = amprise * shrinkage;
  5829. newamp = envfoot + newamprise;
  5830. thisamp[n] = (float)newamp;
  5831. }
  5832. } else // ELSE if only 1 specenv3val, which will be (start or end) trof,
  5833. n = 1; // set another specenv3val to the other (end or start) trof
  5834. if(hi) { // If falling off top of range
  5835. thisamp[n] = hitrofamp; // Keep the upper trof value at end of new, shrunk formant
  5836. thisfrq[n] = frqlimit; // But set its centre, & its upper limit, to the upper frqlimit
  5837. thispch[n] = (float)log10(frqlimit);
  5838. } else { // If falling off bottom of range
  5839. thisamp[0] = lotrofamp; // Keep the lower trof value at start of new, shrunk formant
  5840. thisfrq[0] = frqlimit; // Force specchan centre to be at lofrqlimit
  5841. thispch[0] = (float)log10(frqlimit);
  5842. }
  5843. n++;
  5844. *nuchanlen = n;
  5845. return FINISHED;
  5846. }
  5847. /**************************** GETSPECENV3AMP *************************/
  5848. int getspecenv3amp(double frq,double *amp,float *thispch,float *thisamp,int speccnt,dataptr dz)
  5849. {
  5850. double pp, ratio, ampdiff;
  5851. int z = 0;
  5852. if(speccnt == 0) { /* FORMANT NOT ACTIVE */
  5853. *amp = -1.0; /* flag no amp specified */
  5854. return(FINISHED);
  5855. }
  5856. if(frq<0.0) { /* FREQ NOT AVAILABLE */
  5857. *amp = -1.0; /* flag no amp specified */
  5858. return(FINISHED);
  5859. }
  5860. if(frq<=1.0) /* if frq very low, specify pitch 0.0 */
  5861. pp = 0.0;
  5862. else
  5863. pp = log10(frq);
  5864. if(pp < thispch[0] || pp > thispch[speccnt-1]) {
  5865. *amp = -1.0; /* If pitch out of range of this specenv3 */
  5866. return(FINISHED); /* flag no amp specified */
  5867. }
  5868. while(thispch[z] < pp){ /* Search for channels spanning frequency */
  5869. z++;
  5870. if(z >= speccnt - 1)
  5871. break;
  5872. } /* Interp in specenvamp-envelope to find amp at this frq */
  5873. ratio = (pp - thispch[z-1])/(thispch[z] - thispch[z-1]);
  5874. ampdiff = thisamp[z] - thisamp[z-1];
  5875. *amp = thisamp[z-1] + (ampdiff * ratio);
  5876. *amp = max(0.0,*amp); /* Avoid -ve amps */
  5877. return(FINISHED);
  5878. }
  5879. /**************************** FWINDOW_SIZE *************************/
  5880. int fwindow_size(dataptr dz)
  5881. {
  5882. dz->shortwins = 0;
  5883. switch(dz->mode) {
  5884. case(F_NARROW): if(dz->vflag[NRW_SW]) dz->shortwins = 1; break;
  5885. case(F_SQUEEZE): if(dz->vflag[SQZ_SW]) dz->shortwins = 1; break;
  5886. case(F_NEGATE): break; // Does not extract spectral envelope, but sues array to store OLD contour
  5887. case(F_MAKEFILT): if(dz->vflag[FLT_SW]) dz->shortwins = 1; break;
  5888. case(F_MOVE): // fall thro
  5889. case(F_MOVE2): if(dz->vflag[MOV_SW]) dz->shortwins = 1; break;
  5890. case(F_INVERT): if(dz->vflag[INVERT_SW]) dz->shortwins = 1; break;
  5891. case(F_ROTATE): if(dz->vflag[ROTATE_SW]) dz->shortwins = 1; break;
  5892. case(F_SUPPRESS): if(dz->vflag[SUPPRESS_SW]) dz->shortwins = 1; break;
  5893. case(F_SEE): if(dz->vflag[SEE_SW]) dz->shortwins = 1; break;
  5894. case(F_SEEPKS): if(dz->vflag[SEEPKS_SW]) dz->shortwins = 1; break;
  5895. case(F_SINUS): if(dz->vflag[FSIN_SW]) dz->shortwins = 1; break;
  5896. case(F_ARPEG): // fall_thro
  5897. case(F_OCTSHIFT): // fall_thro
  5898. case(F_TRANS): // fall_thro
  5899. case(F_FRQSHIFT): // fall_thro
  5900. case(F_RESPACE): // fall_thro
  5901. case(F_PINVERT): // fall_thro
  5902. case(F_PEXAGG): // fall_thro
  5903. case(F_PQUANT): // fall thro
  5904. case(F_PCHRAND): // fall thro
  5905. case(F_RAND): if(dz->vflag[RECOLOR_SW]) dz->shortwins = 1; break;
  5906. case(F_SYLABTROF): break;
  5907. default:
  5908. sprintf(errstr,"Unknown mode in small-window check\n");
  5909. return PROGRAM_ERROR;
  5910. }
  5911. return FINISHED;
  5912. }
  5913. //////////////////////////////////
  5914. // GETTING THE PITCH //
  5915. //////////////////////////////////
  5916. /***************************** INITIALISE_PITCHWORK *************************/
  5917. int initialise_pitchwork(int is_launched,dataptr dz)
  5918. {
  5919. int exit_status;
  5920. if((exit_status = establish_arrays_for_pitchwork(dz))<0) {
  5921. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  5922. return(FAILED);
  5923. }
  5924. dz->fsil_ratio = FSILENCE_RATIO/20.0;
  5925. dz->fsil_ratio = pow(10.0,dz->fsil_ratio);
  5926. dz->fsil_ratio = 1.0/dz->fsil_ratio;
  5927. initrand48(); // Possibly needed
  5928. if((exit_status = setup_ring(dz))<0) // Establish ring used for pitch-detection
  5929. return(exit_status);
  5930. return FINISHED;
  5931. }
  5932. /***************************** ESTABLISH_ARRAYS_FOR_PITCHWORK *************************/
  5933. int establish_arrays_for_pitchwork(dataptr dz)
  5934. {
  5935. int i;
  5936. if((dz->parray[P_PRETOTAMP] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
  5937. sprintf(errstr,"INSUFFICIENT MEMORY for amp totalling array.\n");
  5938. return(MEMORY_ERROR);
  5939. }
  5940. if(dz->mode == F_SYLABTROF)
  5941. return(FINISHED);
  5942. if((dz->parray[RUNNINGAVRG] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
  5943. sprintf(errstr,"INSUFFICIENT MEMORY for running averages array.\n");
  5944. return(MEMORY_ERROR);
  5945. }
  5946. if((dz->parray[RUNAVGDURS] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
  5947. sprintf(errstr,"INSUFFICIENT MEMORY for running average durations array.\n");
  5948. return(MEMORY_ERROR);
  5949. }
  5950. if((dz->lparray[AVSTT] = (int *)malloc(dz->wlength * sizeof(int)))==NULL) {
  5951. sprintf(errstr,"INSUFFICIENT MEMORY for running averages window-position array.\n");
  5952. return(MEMORY_ERROR);
  5953. }
  5954. //RWD NOV97 quick solution to unassigned value somewhere in spec pitch!
  5955. for(i = 0; i < dz->wlength;i++)
  5956. dz->parray[P_PRETOTAMP][i] = 0.0;
  5957. if((dz->pitches = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
  5958. sprintf(errstr,"INSUFFICIENT MEMORY for pitches array.\n");
  5959. return(MEMORY_ERROR);
  5960. }
  5961. if(dz->mode == F_PQUANT || dz->mode == F_PCHRAND) {
  5962. if((dz->pitches2 = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
  5963. sprintf(errstr,"INSUFFICIENT MEMORY for pitches array.\n");
  5964. return(MEMORY_ERROR);
  5965. }
  5966. }
  5967. return(FINISHED);
  5968. }
  5969. /****************************** SPECPITCH *******************************
  5970. *
  5971. * (1) Ignore partials below low limit of pitch.
  5972. * (2) If this channel data is louder than any existing piece of data in ring.
  5973. * (Ring data is ordered loudness-wise)...
  5974. * (3) If this freq is too close to an existing frequency..
  5975. * (4) and if it is louder than that existing frequency data..
  5976. * (5) Substitute in in the ring.
  5977. * (6) Otherwise, (its a new frq) insert it into the ring.
  5978. */
  5979. int specpitch(int inner_lpcnt,double *target, dataptr dz)
  5980. {
  5981. int exit_status;
  5982. int vc, pitchcc;
  5983. chvptr here, there, *partials;
  5984. float minamp, newfrq;
  5985. double loudest_partial_frq, nextloudest_partial_frq, lo_loud_partial, hi_loud_partial, thepitch;
  5986. if((partials = (chvptr *)malloc(FMAXIMI * sizeof(chvptr)))==NULL) {
  5987. sprintf(errstr,"INSUFFICIENT MEMORY for partials array.\n");
  5988. return(MEMORY_ERROR);
  5989. }
  5990. if((exit_status = initialise_ring_vals(FMAXIMI,-1.0,dz))<0)
  5991. return(exit_status);
  5992. for(vc=0;vc<dz->wanted;vc+=2) {
  5993. here = dz->ringhead;
  5994. if(dz->flbufptr[0][FREQ] > VOICELO) { /* 1 */
  5995. do {
  5996. if(dz->flbufptr[0][AMPP] > here->val) { /* 2 */
  5997. if((exit_status = close_to_frq_already_in_ring(&there,(double)dz->flbufptr[0][FREQ],dz))<0)
  5998. return(exit_status);
  5999. if(exit_status==TRUE) {
  6000. if(dz->flbufptr[0][AMPP] > there->val) { /* 4 */
  6001. if((exit_status = substitute_in_ring(vc,here,there,dz))<0) /* 5 */
  6002. return(exit_status);
  6003. }
  6004. } else { /* 6 */
  6005. if((exit_status = insert_in_ring(vc,here,dz))<0)
  6006. return(exit_status);
  6007. }
  6008. break;
  6009. }
  6010. } while((here = here->next)!=dz->ringhead);
  6011. }
  6012. }
  6013. loudest_partial_frq = dz->flbufptr[0][dz->ringhead->loc + 1];
  6014. nextloudest_partial_frq = dz->flbufptr[0][dz->ringhead->next->loc + 1];
  6015. if(loudest_partial_frq < nextloudest_partial_frq) {
  6016. lo_loud_partial = loudest_partial_frq;
  6017. hi_loud_partial = nextloudest_partial_frq;
  6018. } else {
  6019. lo_loud_partial = nextloudest_partial_frq;
  6020. hi_loud_partial = loudest_partial_frq;
  6021. }
  6022. if((exit_status = put_ring_frqs_in_ascending_order(&partials,&minamp,dz))<0)
  6023. return(exit_status);
  6024. if((exit_status = found_pitch(partials,lo_loud_partial,hi_loud_partial,minamp,&thepitch,dz))<0)
  6025. return(exit_status);
  6026. if(exit_status==TRUE) {
  6027. if((exit_status = locate_channel_of_pitch(inner_lpcnt,(float)thepitch,&pitchcc,dz))<0)
  6028. return(exit_status);
  6029. if((exit_status = find_fundamental((float)thepitch,*target,pitchcc,&newfrq,dz))<0)
  6030. return(exit_status);
  6031. *target = (newfrq + *target)/2.0; // target pitch is a running average
  6032. dz->pitches[dz->total_windows] = (float)thepitch;
  6033. } else
  6034. dz->pitches[dz->total_windows] = (float)NOT_PITCH;
  6035. if((exit_status = smooth_spurious_octave_leaps(dz->total_windows,minamp,dz))<0)
  6036. return(exit_status);
  6037. return FINISHED;
  6038. }
  6039. /**************************** CLOSE_TO_FRQ_ALREADY_IN_RING *******************************/
  6040. int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz)
  6041. {
  6042. double frq2, frqratio;
  6043. *there = dz->ringhead;
  6044. do {
  6045. if((*there)->val > 0.0) {
  6046. frq2 = dz->flbufptr[0][(*there)->loc + 1];
  6047. if(frq1 > frq2)
  6048. frqratio = frq1/frq2;
  6049. else
  6050. frqratio = frq2/frq1;
  6051. if(frqratio < EIGHT_OVER_SEVEN)
  6052. return(TRUE);
  6053. }
  6054. } while((*there = (*there)->next) != dz->ringhead);
  6055. return(FALSE);
  6056. }
  6057. /******************************* SUBSITUTE_IN_RING **********************/
  6058. int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz)
  6059. {
  6060. chvptr spare, previous;
  6061. if(here!=there) {
  6062. if(there==dz->ringhead) {
  6063. sprintf(errstr,"IMPOSSIBLE! in substitute_in_ring()\n");
  6064. return(PROGRAM_ERROR);
  6065. }
  6066. spare = there;
  6067. there->next->last = there->last; /* SPLICE REDUNDANT STRUCT FROM RING */
  6068. there->last->next = there->next;
  6069. previous = here->last;
  6070. previous->next = spare; /* SPLICE ITS ADDRESS-SPACE BACK INTO RING */
  6071. spare->last = previous; /* IMMEDIATELY BEFORE HERE */
  6072. here->last = spare;
  6073. spare->next = here;
  6074. if(here==dz->ringhead) /* IF HERE IS RINGHEAD, MOVE RINGHEAD */
  6075. dz->ringhead = spare;
  6076. here = spare; /* POINT TO INSERT LOCATION */
  6077. }
  6078. here->val = dz->flbufptr[0][AMPP]; /* IF here==there */
  6079. here->loc = vc; /* THIS WRITES OVER VAL IN EXISTING RING LOCATION */
  6080. return(FINISHED);
  6081. }
  6082. /*************************** INSERT_IN_RING ***************************/
  6083. int insert_in_ring(int vc, chvptr here, dataptr dz)
  6084. {
  6085. chvptr previous, newend, spare;
  6086. if(here==dz->ringhead) {
  6087. dz->ringhead = dz->ringhead->last;
  6088. spare = dz->ringhead;
  6089. } else {
  6090. if(here==dz->ringhead->last)
  6091. spare = here;
  6092. else {
  6093. spare = dz->ringhead->last;
  6094. newend = dz->ringhead->last->last; /* cut ENDADR (spare) out of ring */
  6095. dz->ringhead->last = newend;
  6096. newend->next = dz->ringhead;
  6097. previous = here->last;
  6098. here->last = spare; /* reuse spare address at new loc by */
  6099. spare->next = here; /* inserting it back into ring before HERE */
  6100. previous->next = spare;
  6101. spare->last = previous;
  6102. }
  6103. }
  6104. spare->val = dz->flbufptr[0][vc]; /* Store new val in spare ring location */
  6105. spare->loc = vc;
  6106. return(FINISHED);
  6107. }
  6108. /************************** PUT_RING_FRQS_IN_ASCENDING_ORDER **********************/
  6109. int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz)
  6110. {
  6111. int k;
  6112. chvptr start, ggot, here = dz->ringhead;
  6113. float minpitch;
  6114. *minamp = (float)MAXFLOAT;
  6115. for(k=0;k<FMAXIMI;k++) {
  6116. if((*minamp = min(dz->flbufptr[0][here->loc],*minamp))>=(float)MAXFLOAT) {
  6117. sprintf(errstr,"Problem with amplitude out of range: put_ring_frqs_in_ascending_order()\n");
  6118. return(PROGRAM_ERROR);
  6119. }
  6120. (here->loc)++; /* CHANGE RING TO POINT TO FRQS, not AMPS */
  6121. here->val = dz->flbufptr[0][here->loc];
  6122. here = here->next;
  6123. }
  6124. here = dz->ringhead;
  6125. minpitch = dz->flbufptr[0][here->loc];
  6126. for(k=1;k<FMAXIMI;k++) {
  6127. start = ggot = here;
  6128. while((here = here->next)!=start) { /* Find lowest frq */
  6129. if(dz->flbufptr[0][here->loc] < minpitch) {
  6130. minpitch = dz->flbufptr[0][here->loc];
  6131. ggot = here;
  6132. }
  6133. }
  6134. (*partials)[k-1] = ggot; /* Save its address */
  6135. here = ggot->next; /* Move to next ring site */
  6136. minpitch = dz->flbufptr[0][here->loc]; /* Preset minfrq to val there */
  6137. ggot->last->next = here; /* Unlink ringsite ggot */
  6138. here->last = ggot->last;
  6139. }
  6140. (*partials)[k-1] = here; /* Remaining ringsite is maximum */
  6141. here = dz->ringhead = (*partials)[0]; /* Reconstruct ring */
  6142. for(k=1;k<FMAXIMI;k++) {
  6143. here->next = (*partials)[k];
  6144. (*partials)[k]->last = here;
  6145. here = here->next;
  6146. }
  6147. here->next = dz->ringhead; /* Close up ring */
  6148. dz->ringhead->last = here;
  6149. return(FINISHED);
  6150. }
  6151. /****************************** FOUND_PITCH **************************/
  6152. int found_pitch(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,double *thepitch,dataptr dz)
  6153. {
  6154. int n, m, k, maximi_less_one = MAXIMUM_PARTIAL - 1, endd = 0;
  6155. double whole_number_ratio, comparison_frq;
  6156. for(n=1;n<maximi_less_one;n++) {
  6157. for(m=n+1;m<MAXIMUM_PARTIAL;m++) { /* NOV 7 */
  6158. whole_number_ratio = (double)m/(double)n;
  6159. comparison_frq = lo_loud_partial * whole_number_ratio;
  6160. if(equivalent_pitches(comparison_frq,hi_loud_partial,dz))
  6161. endd = (MAXIMUM_PARTIAL/m) * n; /* explanation at foot of file */
  6162. else if(comparison_frq > hi_loud_partial)
  6163. break;
  6164. for(k=n;k<=endd;k+=n) {
  6165. *thepitch = lo_loud_partial/(double)k;
  6166. if(*thepitch>FPICH_HILM)
  6167. continue;
  6168. if(*thepitch<SPEC_MINFRQ)
  6169. break;
  6170. if(is_peak_at(*thepitch,0,minamp,dz)){
  6171. if(enough_partials_are_harmonics(partials,*thepitch,dz))
  6172. return TRUE;
  6173. }
  6174. }
  6175. }
  6176. }
  6177. return(FALSE);
  6178. }
  6179. /************************ SMOOTH_SPURIOUS_OCTAVE_LEAPS ***************************/
  6180. int smooth_spurious_octave_leaps(int pitchno,float minamp,dataptr dz)
  6181. {
  6182. double thispitch = dz->pitches[pitchno];
  6183. double startpitch, lastpitch;
  6184. int k = 0;
  6185. if(pitchno<=0)
  6186. return(FINISHED);
  6187. lastpitch = dz->pitches[pitchno-1];
  6188. if(lastpitch > SPEC_MINFRQ && thispitch > SPEC_MINFRQ) { /* OCTAVE ADJ HERE */
  6189. if(thispitch > lastpitch) { /* OCTAVE ADJ FORWARDS */
  6190. startpitch = thispitch;
  6191. while(thispitch/lastpitch > ALMOST_TWO)
  6192. thispitch /= 2.0;
  6193. if(thispitch!=startpitch) {
  6194. if(thispitch < SPEC_MINFRQ)
  6195. return(FINISHED);
  6196. if(is_peak_at(thispitch,0L,minamp,dz))
  6197. dz->pitches[pitchno] = (float)thispitch;
  6198. else
  6199. dz->pitches[pitchno] = (float)startpitch;
  6200. }
  6201. return(FINISHED);
  6202. } else {
  6203. while(pitchno>=1) { /* OCTAVE ADJ BCKWARDS */
  6204. k++;
  6205. if((thispitch = dz->pitches[pitchno--])<SPEC_MINFRQ)
  6206. return(FINISHED);
  6207. if((lastpitch = dz->pitches[pitchno])<SPEC_MINFRQ)
  6208. return(FINISHED);
  6209. startpitch = lastpitch;
  6210. while(lastpitch/thispitch > ALMOST_TWO)
  6211. lastpitch /= 2.0;
  6212. if(lastpitch!=startpitch) {
  6213. if(lastpitch < SPEC_MINFRQ)
  6214. return(FINISHED);
  6215. if(is_peak_at(lastpitch,k,minamp,dz))
  6216. dz->pitches[pitchno] = (float)lastpitch;
  6217. else
  6218. dz->pitches[pitchno] = (float)startpitch;
  6219. }
  6220. }
  6221. }
  6222. }
  6223. return(FINISHED);
  6224. }
  6225. /*************************** IS_PEAK_AT ***************************/
  6226. int is_peak_at(double frq,int window_offset,float minamp,dataptr dz)
  6227. {
  6228. float *thisbuf;
  6229. int cc, vc, searchtop, searchbot;
  6230. if(window_offset) { /* BAKTRAK ALONG BIGBUF, IF NESS */
  6231. thisbuf = dz->flbufptr[0] - (window_offset * dz->wanted);
  6232. if((int)thisbuf < 0 || thisbuf < dz->bigfbuf || thisbuf >= dz->flbufptr[2])
  6233. return(FALSE);
  6234. } else
  6235. thisbuf = dz->flbufptr[0];
  6236. cc = (int)((frq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  6237. searchtop = min(dz->clength,cc + FCHANSCAN + 1);
  6238. searchbot = max(0,cc - FCHANSCAN);
  6239. for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
  6240. if(!equivalent_pitches((double)thisbuf[vc+1],frq,dz)) {
  6241. continue;
  6242. }
  6243. if(thisbuf[vc] < minamp * FPEAK_LIMIT)
  6244. continue;
  6245. if(local_peak(cc,frq,thisbuf,dz))
  6246. return TRUE;
  6247. }
  6248. return FALSE;
  6249. }
  6250. /***************************** LOCAL_PEAK **************************/
  6251. int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz)
  6252. {
  6253. int thisvc = thiscc * 2;
  6254. int cc, vc, searchtop, searchbot;
  6255. double frqtop = frq * SEMITONE_INTERVAL;
  6256. double frqbot = frq / SEMITONE_INTERVAL;
  6257. searchtop = (int)((frqtop + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  6258. searchtop = min(dz->clength,searchtop + PEAKSCAN + 1);
  6259. searchbot = (int)((frqbot + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  6260. searchbot = max(0,searchbot - PEAKSCAN);
  6261. for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
  6262. if(thisbuf[thisvc] < thisbuf[vc])
  6263. return(FALSE);
  6264. }
  6265. return(TRUE);
  6266. }
  6267. /**************************** ENOUGH_PARTIALS_ARE_HARMONICS *************************/
  6268. int enough_partials_are_harmonics(chvptr *partials,double thepitch,dataptr dz)
  6269. {
  6270. int n, good_match = 0;
  6271. double thisfrq;
  6272. for(n=0;n<FMAXIMI;n++) {
  6273. if((thisfrq = dz->flbufptr[0][partials[n]->loc]) < thepitch)
  6274. continue;
  6275. if(is_equivalent_pitch(thisfrq,thepitch,dz)){
  6276. if(++good_match >= GOOD_MATCH)
  6277. return TRUE;
  6278. }
  6279. }
  6280. return FALSE;
  6281. }
  6282. /**************************** IS_EQUIVALENT_PITCH *************************/
  6283. int is_equivalent_pitch(double frq1,double frq2,dataptr dz)
  6284. {
  6285. double ratio = frq1/frq2;
  6286. int iratio = round(ratio);
  6287. double intvl;
  6288. ratio = frq1/frq2;
  6289. iratio = round(ratio);
  6290. if(ratio > iratio)
  6291. intvl = ratio/(double)iratio;
  6292. else
  6293. intvl = (double)iratio/ratio;
  6294. if(intvl > SEMITONE_INTERVAL)
  6295. return(FALSE);
  6296. return(TRUE);
  6297. }
  6298. /**************************** IS_ABOVE_EQUIVALENT_PITCH *************************/
  6299. int is_above_equivalent_pitch(double frq1,double frq2,dataptr dz)
  6300. {
  6301. double ratio = frq1/frq2;
  6302. int iratio = round(ratio);
  6303. double intvl;
  6304. ratio = frq1/frq2;
  6305. iratio = round(ratio);
  6306. intvl = ratio/(double)iratio;
  6307. if(intvl > SEMITONE_INTERVAL)
  6308. return(FALSE);
  6309. return(TRUE);
  6310. }
  6311. // SMOOTHING AND VERIFYING PITCH
  6312. /***************************** TIDY_UP_PITCH_DATA ***********************/
  6313. int tidy_up_pitch_data(dataptr dz)
  6314. {
  6315. int exit_status;
  6316. if((exit_status = anti_noise_smoothing(dz->wlength,dz->pitches,dz->frametime))<0)
  6317. return(exit_status);
  6318. if((exit_status = continuity_smoothing(dz))<0)
  6319. return(exit_status);
  6320. if((exit_status = mark_zeros_in_pitchdata(dz))<0)
  6321. return(exit_status);
  6322. if((exit_status = eliminate_blips_in_pitch_data(dz))<0)
  6323. return(exit_status);
  6324. if((exit_status = interpolate_pitch(dz))<0)
  6325. return exit_status;
  6326. return pitch_found(dz);
  6327. }
  6328. /**************************** PITCH_FOUND ****************************/
  6329. int pitch_found(dataptr dz)
  6330. {
  6331. int n;
  6332. for(n=0;n<dz->wlength;n++) {
  6333. if(dz->pitches[n] > NOT_PITCH)
  6334. return(FINISHED);
  6335. }
  6336. sprintf(errstr,"No valid pitch found.\n");
  6337. return(GOAL_FAILED);
  6338. }
  6339. /********************************** MARK_ZEROS_IN_PITCHDATA ************************
  6340. *
  6341. * Disregard data on windows which are FSILENCE_RATIO below maximum level.
  6342. */
  6343. int mark_zeros_in_pitchdata(dataptr dz)
  6344. {
  6345. int n;
  6346. double maxlevel = 0.0, minlevel;
  6347. for(n=0;n<dz->wlength;n++) {
  6348. if(dz->parray[P_PRETOTAMP][n] > maxlevel)
  6349. maxlevel = dz->parray[P_PRETOTAMP][n];
  6350. }
  6351. minlevel = maxlevel * dz->fsil_ratio;
  6352. for(n=0;n<dz->wlength;n++) {
  6353. if(dz->parray[P_PRETOTAMP][n] < minlevel)
  6354. dz->pitches[n] = (float)NOT_SOUND;
  6355. }
  6356. return(FINISHED);
  6357. }
  6358. /************************** ELIMINATE_BLIPS_IN_PITCH_DATA ****************************
  6359. *
  6360. * (1) Eliminate any group of FBLIPLEN pitched windows, bracketed by
  6361. * unpitched windows, as unreliable data.
  6362. */
  6363. int eliminate_blips_in_pitch_data(dataptr dz)
  6364. {
  6365. int n, m, k, wlength_less_bliplen;
  6366. int OK = 1;
  6367. wlength_less_bliplen = dz->wlength - FBLIPLEN;
  6368. for(n=1;n<wlength_less_bliplen;n++) {
  6369. if(dz->pitches[n] > 0.0) {
  6370. if(dz->pitches[n-1] < 0.0) {
  6371. for(k = 1; k <= FBLIPLEN; k++) {
  6372. if(dz->pitches[n+k] < 0.0) {
  6373. for(m=0;m<k;m++)
  6374. dz->pitches[n+m] = (float)NOT_PITCH;
  6375. n += k;
  6376. continue;
  6377. }
  6378. }
  6379. }
  6380. }
  6381. }
  6382. n = wlength_less_bliplen;
  6383. if((dz->pitches[n] > 0.0) && (dz->pitches[n-1] < 0.0)) {
  6384. for(k = 1; k < FBLIPLEN; k++) {
  6385. if(dz->pitches[n+k] < 0.0)
  6386. OK = 0;
  6387. break;
  6388. }
  6389. }
  6390. if(!OK) {
  6391. for(n=wlength_less_bliplen;n<dz->wlength;n++)
  6392. dz->pitches[n] = (float)NOT_PITCH;
  6393. }
  6394. return(FINISHED);
  6395. }
  6396. /********************** ANTI_NOISE_SMOOTHING *********************/
  6397. int anti_noise_smoothing(int wlength,float *pitches,float frametime)
  6398. {
  6399. char *smooth;
  6400. double max_pglide;
  6401. int n;
  6402. if(wlength < FMIN_SMOOTH_SET + 1)
  6403. return(FINISHED);
  6404. max_pglide = pow(2.0,FMAX_GLISRATE) * frametime;
  6405. if((smooth = (char *)malloc((size_t)wlength))==NULL) {
  6406. sprintf(errstr,"aINSUFFICIENT MEMORY for smoothing array.\n");
  6407. return(MEMORY_ERROR);
  6408. }
  6409. for(n=1;n<wlength-1;n++)
  6410. smooth[n] = (char)is_smooth_from_both_sides(n,max_pglide,pitches);
  6411. smooth[0] = (char)is_initialpitch_smooth(smooth,max_pglide,pitches);
  6412. smooth[wlength-1] = (char)is_finalpitch_smooth(smooth,max_pglide,wlength,pitches);
  6413. for(n=FMIN_SMOOTH_SET-1;n<wlength;n++) {
  6414. if(!smooth[n])
  6415. smooth[n] = (char)is_smooth_from_before(n,smooth,max_pglide,pitches);
  6416. }
  6417. for(n=0;n<=wlength-FMIN_SMOOTH_SET;n++) {
  6418. if(!smooth[n])
  6419. smooth[n] = (char)is_smooth_from_after(n,smooth,max_pglide,pitches);
  6420. }
  6421. test_glitch_sets(smooth,max_pglide,wlength,pitches);
  6422. remove_unsmooth_pitches(smooth,wlength,pitches);
  6423. free(smooth);
  6424. return(FINISHED);
  6425. }
  6426. /********************** IS_SMOOTH_FROM_BOTH_SIDES *********************
  6427. *
  6428. * verify a pitch if it has continuity with the pitches on either side.
  6429. */
  6430. int is_smooth_from_both_sides(int n,double max_pglide,float *pitches)
  6431. {
  6432. float thispitch, pitch_before, pitch_after;
  6433. double pre_interval, post_interval;
  6434. if((thispitch = pitches[n]) < FLTERR)
  6435. return FALSE;
  6436. if((pitch_before = pitches[n-1]) < FLTERR)
  6437. return FALSE;
  6438. if((pitch_after = pitches[n+1]) < FLTERR)
  6439. return FALSE;
  6440. pre_interval = pitch_before/thispitch;
  6441. if(pre_interval < 1.0)
  6442. pre_interval = 1.0/pre_interval;
  6443. post_interval = pitch_after/thispitch;
  6444. if(post_interval < 1.0)
  6445. post_interval = 1.0/post_interval;
  6446. if(pre_interval > max_pglide
  6447. || post_interval > max_pglide)
  6448. return FALSE;
  6449. return TRUE;
  6450. }
  6451. /********************** IS_INITIALPITCH_SMOOTH *********************
  6452. *
  6453. * verify first pitch if it has continuity with an ensuing verified pitch.
  6454. */
  6455. int is_initialpitch_smooth(char *smooth,double max_pglide,float *pitches)
  6456. {
  6457. float thispitch;
  6458. int n;
  6459. double post_interval;
  6460. if((thispitch = pitches[0]) < FLTERR)
  6461. return FALSE;
  6462. for(n=1;n < FMIN_SMOOTH_SET;n++) {
  6463. if(smooth[n]) {
  6464. post_interval = pitches[n]/pitches[0];
  6465. if(post_interval < 1.0)
  6466. post_interval = 1.0/post_interval;
  6467. if(post_interval <= pow(max_pglide,(double)n))
  6468. return TRUE;
  6469. }
  6470. }
  6471. return(FALSE);
  6472. }
  6473. /********************** IS_FINALPITCH_SMOOTH *********************
  6474. *
  6475. * verify final pitch if it has continuity with a preceding verified pitch.
  6476. */
  6477. int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,float *pitches)
  6478. {
  6479. float thispitch;
  6480. double pre_interval;
  6481. int n;
  6482. int last = wlength - 1;
  6483. if((thispitch = pitches[last]) < FLTERR)
  6484. return FALSE;
  6485. for(n=1;n < FMIN_SMOOTH_SET;n++) {
  6486. if(smooth[last-n]) {
  6487. pre_interval = pitches[last-n]/pitches[last];
  6488. if(pre_interval < 1.0)
  6489. pre_interval = 1.0/pre_interval;
  6490. if(pre_interval <= pow(max_pglide,(double)n))
  6491. return TRUE;
  6492. }
  6493. }
  6494. return(FALSE);
  6495. }
  6496. /********************** IS_SMOOTH_FROM_BEFORE *********************
  6497. *
  6498. * verify a pitch which has continuity with a preceding set of verified pitches.
  6499. */
  6500. int is_smooth_from_before(int n,char *smooth,double max_pglide,float *pitches)
  6501. {
  6502. float thispitch, pitch_before;
  6503. double pre_interval;
  6504. int m;
  6505. if((thispitch = pitches[n]) < FLTERR)
  6506. return FALSE;
  6507. for(m=1;m<FMIN_SMOOTH_SET;m++) { /* If there are (FMIN_SMOOTH_SET-1) smooth pitches before */
  6508. if(!smooth[n-m])
  6509. return(FALSE);
  6510. }
  6511. pitch_before = pitches[n-1]; /* Test the interval with the previous pitch */
  6512. pre_interval = pitch_before/thispitch;
  6513. if(pre_interval < 1.0)
  6514. pre_interval = 1.0/pre_interval;
  6515. if(pre_interval > max_pglide)
  6516. return FALSE; /* And if it's acceptably smooth */
  6517. return TRUE; /* mark this pitch as smooth also */
  6518. }
  6519. /********************** IS_SMOOTH_FROM_AFTER *********************
  6520. *
  6521. * verify a pitch which has continuity with a following set of verified pitches.
  6522. */
  6523. int is_smooth_from_after(int n,char *smooth,double max_pglide,float *pitches)
  6524. {
  6525. float thispitch, pitch_after;
  6526. double post_interval;
  6527. int m;
  6528. if((thispitch = pitches[n]) < FLTERR)
  6529. return FALSE;
  6530. for(m=1;m<FMIN_SMOOTH_SET;m++) { /* If there are (FMIN_SMOOTH_SET-1) smooth pitches after */
  6531. if(!smooth[n+m])
  6532. return(FALSE);
  6533. }
  6534. pitch_after = pitches[n+1]; /* Test the interval with the next pitch */
  6535. post_interval = pitch_after/thispitch;
  6536. if(post_interval < 1.0)
  6537. post_interval = 1.0/post_interval;
  6538. if(post_interval > max_pglide)
  6539. return FALSE; /* And if it's acceptably smooth */
  6540. return TRUE; /* mark this pitch as smooth also */
  6541. }
  6542. /********************** TEST_GLITCH_SETS *********************
  6543. *
  6544. * This function looks for any sets of values that appear to be glitches
  6545. * amongst the real pitch data.
  6546. * It is possible some items are REAL pitch data isolated BETWEEN short glitches.
  6547. * This function checks for these cases.
  6548. */
  6549. int test_glitch_sets(char *smooth,double max_pglide,int wlength,float *pitches)
  6550. {
  6551. int exit_status;
  6552. int gotglitch = FALSE;
  6553. int n, gltchend, gltchstart = 0;
  6554. for(n=0;n<wlength;n++) {
  6555. if(gotglitch) { /* if inside a glitch */
  6556. if(smooth[n]) { /* if reached its end, mark the end, then process the glitch */
  6557. gltchend = n;
  6558. if((exit_status = test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches))<0)
  6559. return(exit_status);
  6560. if((exit_status = test_glitch_backwards(gltchstart,gltchend,smooth,max_pglide,wlength,pitches))<0)
  6561. return(exit_status);
  6562. gotglitch = 0;
  6563. }
  6564. } else { /* look for a glitch and mark its start */
  6565. if(!smooth[n]) {
  6566. gotglitch = 1;
  6567. gltchstart = n;
  6568. }
  6569. }
  6570. }
  6571. if(gotglitch) { /* if inside a glitch at end of data, process glitch */
  6572. gltchend = n;
  6573. test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches);
  6574. }
  6575. return(FINISHED);
  6576. }
  6577. /********************* REMOVE_UNSMOOTH_PITCHES ***********************
  6578. *
  6579. * delete all pitches which have no verified continuity with surrounding pitches.
  6580. */
  6581. void remove_unsmooth_pitches(char *smooth,int wlength,float *pitches)
  6582. {
  6583. int n;
  6584. for(n=0;n<wlength;n++) {
  6585. if(!smooth[n])
  6586. pitches[n] = (float)NOT_PITCH;
  6587. }
  6588. }
  6589. /********************** TEST_GLITCH_FORWARDS *********************
  6590. *
  6591. * searching from start of glitch, look for isolated true pitches
  6592. * amongst glitch data.
  6593. */
  6594. #define LAST_SMOOTH_NOT_SET (-1)
  6595. int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,float *pitches)
  6596. {
  6597. int n, glcnt;
  6598. int last_smooth, previous;
  6599. double pre_interval;
  6600. if((previous = gltchstart - 1) < 0)
  6601. return FINISHED;
  6602. if(pitches[previous] < FLTERR) {
  6603. sprintf(errstr,"Error in previous smoothing logic: test_glitch_forwards()\n");
  6604. return(PROGRAM_ERROR);
  6605. }
  6606. last_smooth = previous;
  6607. n = gltchstart+1; /* setup params for local search of glitch */
  6608. glcnt = 1;
  6609. while(n < gltchend) { /* look through the glitch */
  6610. if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
  6611. pre_interval = pitches[n]/pitches[previous];
  6612. if(pre_interval < 1.0)
  6613. pre_interval = 1.0/pre_interval; /* compare against previous verified pitch */
  6614. if(pre_interval <= pow(max_pglide,(double)(n-previous))) {
  6615. smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
  6616. last_smooth = n;
  6617. }
  6618. }
  6619. n++; /* Once more than a max-glitch-set has been scanned */
  6620. /* or the end of the entire glitch is reached */
  6621. if(++glcnt >= FMIN_SMOOTH_SET || n >= gltchend) {
  6622. if(last_smooth == previous)
  6623. break; /* If no new verifiable pitch found, give up */
  6624. previous = last_smooth;
  6625. n = last_smooth + 1; /* Otherwise start a new local search from newly verified pitch */
  6626. glcnt = 1;
  6627. }
  6628. }
  6629. return(FINISHED);
  6630. }
  6631. /********************** TEST_GLITCH_BACKWARDS *********************
  6632. *
  6633. * searching from end of glitch, look for isolated true pitches
  6634. * amongst glitch data.
  6635. */
  6636. int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,double max_pglide,int wlength,float *pitches)
  6637. {
  6638. int n, glcnt, next, next_smooth;
  6639. double post_interval;
  6640. if((next = gltchend) >= wlength)
  6641. return FINISHED;
  6642. if(pitches[next] < FLTERR) {
  6643. sprintf(errstr,"Error in previous smoothing logic: test_glitch_backwards()\n");
  6644. return(PROGRAM_ERROR);
  6645. }
  6646. next_smooth = next;
  6647. n = gltchend-2; /* setup params for local search of glitch */
  6648. glcnt = 1;
  6649. while(n >= gltchstart) { /* look through the glitch */
  6650. if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
  6651. post_interval = pitches[n]/pitches[next];
  6652. if(post_interval < 1.0)
  6653. post_interval = 1.0/post_interval; /* compare against previous verified pitch */
  6654. if(post_interval <= pow(max_pglide,(double)(next - n))) {
  6655. smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
  6656. next_smooth = n;
  6657. }
  6658. }
  6659. n--; /* Once more than a max-glitch-set has been scanned */
  6660. /* or the start of the entire glitch is reached */
  6661. if(++glcnt >= FMIN_SMOOTH_SET || n < gltchstart) {
  6662. if(next_smooth == next)
  6663. break; /* If no new verifiable pitch found, give up */
  6664. next = next_smooth;
  6665. n = next_smooth - 1;
  6666. glcnt = 1; /* Otherwise start a new local search */
  6667. }
  6668. }
  6669. return(FINISHED);
  6670. }
  6671. //////////////////////////////////
  6672. // INTERPOLATING PITCH //
  6673. //////////////////////////////////
  6674. /**************************** INTERPOLATE_PITCH ***************************/
  6675. #define TRUE_UNPITCHED -3
  6676. #define SILENCE_BRACKETED 1
  6677. #define PITCH_BRACKETED 2
  6678. #define PITCH_ONSET 3
  6679. #define PITCH_ENDING 4
  6680. int interpolate_pitch(dataptr dz)
  6681. {
  6682. int exit_status;
  6683. int pitchno, unpitchstart = 0, unpitchcnt = 0, k;
  6684. int min_unpitch_windows = (int)round(TOO_SHORT_UNPICH/dz->frametime);
  6685. int unpitched_eventtype = 0;
  6686. // Eliminate too short unpitched-bloks appropriately to their context //
  6687. if(dz->retain_unpitched_data_for_deletion) {
  6688. for(pitchno=0;pitchno<dz->wlength;pitchno++) {
  6689. if(flteq((double)dz->pitches[pitchno],NOT_SOUND)) { // SILENCE
  6690. if(unpitchcnt == 0)
  6691. continue; // If there's an unpitched blok, it's followed by silence
  6692. if(unpitchcnt > min_unpitch_windows) { // If unpitched is long enough
  6693. for(k = unpitchstart;k < pitchno;k++) // mark as truly unpitched
  6694. dz->pitches[k] = TRUE_UNPITCHED; // Else
  6695. } else {
  6696. for(k = unpitchstart;k < pitchno;k++)
  6697. dz->pitches[k] = NOT_SOUND; // Treat as silence (will be zeroed)
  6698. }
  6699. unpitchcnt = 0;
  6700. } else if(dz->pitches[pitchno] > FSPEC_MINFRQ) { // PITCHED
  6701. if(unpitchcnt == 0)
  6702. continue;
  6703. if(unpitchcnt > min_unpitch_windows) { // If unpitched is long enough
  6704. for(k = unpitchstart;k < pitchno;k++) // mark as truly unpitched
  6705. dz->pitches[k] = TRUE_UNPITCHED; // Else
  6706. } else {
  6707. // Unpitched blok followed by pitch
  6708. if (unpitchstart > 0 && (dz->pitches[unpitchstart-1] > FSPEC_MINFRQ))
  6709. unpitched_eventtype = PITCH_BRACKETED; // Bracketed by pitch
  6710. else // OR
  6711. unpitched_eventtype = PITCH_ONSET; // introduces pitched material (material before unpitched must have been silence)
  6712. switch(unpitched_eventtype) {
  6713. case(PITCH_ONSET):
  6714. for(k = unpitchstart;k < pitchno;k++)
  6715. dz->pitches[k] = NOT_SOUND; // Treat as silence (will be zeroed)
  6716. break;
  6717. case(PITCH_BRACKETED): // will be interpolated to give a pitch value
  6718. break;
  6719. }
  6720. }
  6721. unpitchcnt = 0;
  6722. } else { // UNPITCHED
  6723. if(unpitchcnt == 0)
  6724. unpitchstart = pitchno;
  6725. unpitchcnt++;
  6726. }
  6727. }
  6728. // Deal with any unpitched blok at end of file
  6729. if(unpitchcnt > 0) {
  6730. if(unpitchcnt > min_unpitch_windows) { // If unpitched is long enough
  6731. for(k = unpitchstart;k < dz->wlength;k++) // mark as truly unpitched
  6732. dz->pitches[k] = TRUE_UNPITCHED;
  6733. } else { // Else
  6734. if (unpitchstart > 0 && (dz->pitches[unpitchstart-1] >= FSPEC_MINFRQ))
  6735. unpitched_eventtype = PITCH_ENDING; // Preceded by pitch
  6736. else // OR
  6737. unpitched_eventtype = SILENCE_BRACKETED; // material before unpitched must have been silence
  6738. switch(unpitched_eventtype) {
  6739. case(SILENCE_BRACKETED):
  6740. for(k = unpitchstart;k < pitchno;k++)
  6741. dz->pitches[k] = NOT_SOUND; // Treat as silence (will be zeroed)
  6742. break;
  6743. case(PITCH_ENDING): // will be interpolated to give a pitch value
  6744. break;
  6745. }
  6746. }
  6747. }
  6748. }
  6749. // We now have a file with (1) PITCH, (2) Interpolatable stretches of NON_PICH, (3) TRUE_UNPITCHED and (4) NOT_SOUND
  6750. for(pitchno=0;pitchno<dz->wlength;pitchno++) {
  6751. if(dz->pitches[pitchno] < FSPEC_MINFRQ) {
  6752. if(dz->retain_unpitched_data_for_deletion && dz->pitches[pitchno] <= NOT_SOUND)
  6753. continue;
  6754. if((exit_status = do_interpolating(&pitchno,dz->retain_unpitched_data_for_deletion,dz))<0)
  6755. return(exit_status);
  6756. }
  6757. }
  6758. // Restore the NOT_PITCH flags to the material which is TRUE_UNPITCHED so we have a file with pitch, non-pitch (-1) and not_sound (-2)
  6759. if(dz->retain_unpitched_data_for_deletion) {
  6760. for(pitchno=0;pitchno<dz->wlength;pitchno++) {
  6761. if(flteq((double)dz->pitches[pitchno],TRUE_UNPITCHED))
  6762. dz->pitches[pitchno] = NOT_PITCH;
  6763. }
  6764. }
  6765. return(FINISHED);
  6766. }
  6767. /****************************** DO_INTERPOLATING *************************/
  6768. int do_interpolating(int *pitchno,int retain_unpitched_data_for_deletion,dataptr dz)
  6769. {
  6770. int act_type = FMID_PITCH;
  6771. int start = *pitchno, m;
  6772. double startpitch, endpitch, thispitch, lastpitch, pstep;
  6773. if(*pitchno==0L) // Window is at start of file
  6774. act_type = FFIRST_PITCH;
  6775. while(dz->pitches[*pitchno] < FSPEC_MINFRQ) { // If window is unpitched, advance until we find a pitched window
  6776. if(++(*pitchno)>=dz->wlength) { // IF we reach end of file without finding pitched window
  6777. if(act_type == FFIRST_PITCH) // if we started search at file start,
  6778. act_type = FNO_PITCH; // there is no pitch to find in the file.
  6779. else
  6780. act_type = FEND_PITCH; // otherwise this is an unpitched blok at file end
  6781. break;
  6782. }
  6783. }
  6784. if(act_type==FMID_PITCH) { // As default, this is an unpitched blok in mid file
  6785. m = start-1; // search backwards for a valid pitch
  6786. while(dz->pitches[m] < FSPEC_MINFRQ) {
  6787. if(--m <= 0) { // and if we reach file start without finding one
  6788. act_type = FFIRST_PITCH; // this is an unpitched blok at file start
  6789. break;
  6790. }
  6791. }
  6792. start = m;
  6793. }
  6794. switch(act_type) {
  6795. case(FMID_PITCH):
  6796. startpitch = hz_to_pitchheight((double)dz->pitches[start-1]);
  6797. endpitch = hz_to_pitchheight((double)dz->pitches[*pitchno]);
  6798. pstep = (endpitch - startpitch)/(double)((*pitchno) - (start - 1));
  6799. lastpitch = startpitch;
  6800. for(m=start;m<*pitchno;m++) { // Interp pitch across unpitched seg
  6801. thispitch = lastpitch + pstep;
  6802. if(!(retain_unpitched_data_for_deletion && dz->pitches[m]<=NOT_SOUND)) // i.e. If we are retaining truly non-pitched material and silence
  6803. dz->pitches[m] = (float)pitchheight_to_hz(thispitch); // and this is such material, don't interp!!
  6804. lastpitch = thispitch;
  6805. }
  6806. break;
  6807. case(FFIRST_PITCH):
  6808. for(m=0;m<*pitchno;m++) { // Extend first clear pitch back to start
  6809. if(!(retain_unpitched_data_for_deletion && (dz->pitches[m]<=NOT_SOUND)))
  6810. dz->pitches[m] = dz->pitches[*pitchno];
  6811. }
  6812. break;
  6813. case(FEND_PITCH): // Extend last clear pitch on to end
  6814. for(m=start;m<*pitchno;m++) {
  6815. if(!(retain_unpitched_data_for_deletion && (dz->pitches[m]<=NOT_SOUND)))
  6816. dz->pitches[m] = dz->pitches[start-1];
  6817. }
  6818. break;
  6819. case(FNO_PITCH):
  6820. sprintf(errstr,"No valid pitch found.\n");
  6821. return(GOAL_FAILED);
  6822. }
  6823. (*pitchno)--; // set next interpolation to start at end of this interpolated block
  6824. return(FINISHED);
  6825. }
  6826. /***************************** HZ_TO_PITCHHEIGHT *******************************
  6827. *
  6828. * Real pitch is 12 * log2(frq/basis_frq).
  6829. *
  6830. * BUT (with a little help from the Feynman lectures!!)
  6831. * (1) The basis_frq is arbitrary, and cancels out, so let it be 1.0.
  6832. i.e. pitch1 = 12 * log2(frq1/basis_frq) = 12 * (log2(frq1) - log2(basis_frq));
  6833. pitch2 = 12 * log2(frq2/basis_frq) = 12 * (log2(frq2) - log2(basis_frq));
  6834. pitch1 - pitch2 = 12 * (log2(frq1) - log2(frq2)) = 12 * log2(frq1/frq2);
  6835. * (2) Finding the difference of 2 log2() numbers, interpolating and
  6836. * reconverting to pow(2.0,...) is no different to doing same
  6837. * calculation to base e.
  6838. * (3) The (12 *) is also a cancellable factor in all this.
  6839. * So pitch_height serves the same function as pitch in these calculations!!
  6840. */
  6841. double hz_to_pitchheight(double frqq)
  6842. {
  6843. return log(frqq);
  6844. }
  6845. /***************************** PITCHHEIGHT_TO_HZ *******************************/
  6846. double pitchheight_to_hz(double pitch_height)
  6847. {
  6848. return exp(pitch_height);
  6849. }
  6850. /************************* LOCATE CHANNEL OF FUNDAMENTAL *********************/
  6851. int locate_channel_of_fundamental(int inner_lpcnt,float *fundfrq, int *newcc,dataptr dz)
  6852. {
  6853. double srchbot, srchtop, fundamp, ferror, frq, subfrq = HUGE, top;
  6854. int cc, vc, subchan = 0;
  6855. *fundfrq = (float)dz->pitches[inner_lpcnt];
  6856. if(*fundfrq < 0.0)
  6857. return FINISHED;
  6858. srchbot = *fundfrq * SEVEN_OVER_EIGHT;
  6859. srchtop = *fundfrq * EIGHT_OVER_SEVEN;
  6860. ferror = HUGE;
  6861. if(inner_lpcnt == 0) { // Window zero has no meaningful data
  6862. frq = 0.0; // search using centre and top frqs of frq bins
  6863. top = dz->halfchwidth;
  6864. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  6865. if(top < srchbot) {
  6866. subfrq = frq; // Remember chan-frq and number of the channel before fundamental (should be) found
  6867. subchan = cc;
  6868. } else if(frq < srchtop) { // For any channel in range, find channel-centre closest to fundamental
  6869. if(fabs(*fundfrq - frq) < ferror) {
  6870. ferror = fabs(*fundfrq - frq);
  6871. *newcc = cc;
  6872. }
  6873. } else if(ferror == HUGE) { // If no frequencies within range of fundamental (should be impossible!!), keep closest
  6874. if(fabs(frq - *fundfrq) < fabs(*fundfrq - subfrq))
  6875. *newcc = cc; // If chan-frq above searched-for range is closer than one below, use its channel
  6876. else
  6877. *newcc = subchan; // else use channel below
  6878. break;
  6879. }
  6880. frq += dz->chwidth;
  6881. top += dz->chwidth;
  6882. }
  6883. } else { // Normal case
  6884. fundamp = -HUGE;
  6885. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  6886. frq = dz->flbufptr[0][FREQ];
  6887. if(frq < srchbot) {
  6888. subfrq = frq; // Remember frq and channo in channel before fundamental (should be) found
  6889. subchan = cc;
  6890. } else if(frq < srchtop) {
  6891. if(dz->flbufptr[0][AMPP] > fundamp) { // If (frqs near) fundamental found, find loudest occurence
  6892. fundamp = dz->flbufptr[0][AMPP];
  6893. *newcc = cc;
  6894. }
  6895. } else if(fundamp == -HUGE) { // If no frequencies within range of fundamental, keep closest in frq
  6896. if(subfrq == HUGE)
  6897. *newcc = cc; // If there is no subfrq, use the frq in chan above range
  6898. if(fabs(frq - *fundfrq) < fabs(*fundfrq - subfrq))
  6899. *newcc = cc; // If frq above is closer than one below, use its channel
  6900. else
  6901. *newcc = subchan; // else use channel below
  6902. break;
  6903. }
  6904. }
  6905. }
  6906. return FINISHED;
  6907. }
  6908. /************************* LOCATE_CHANNEL_OF_PITCH *********************/
  6909. int locate_channel_of_pitch(int inner_lpcnt,float thepitch, int *newcc,dataptr dz)
  6910. {
  6911. double srchbot, srchtop, fundamp, ferror, frq, subfrq = HUGE, top;
  6912. int cc, vc, subchan = 0;
  6913. if(thepitch < 0.0) {
  6914. sprintf(errstr,"This process needs interpolated pitch data: the extracted pitchdata still has pitch-zeros or silence-zeros.\n");
  6915. return USER_ERROR;
  6916. }
  6917. srchbot = thepitch * SEVEN_OVER_EIGHT;
  6918. srchtop = thepitch * EIGHT_OVER_SEVEN;
  6919. ferror = HUGE;
  6920. if(inner_lpcnt == 0) { // Window zero has no meaningful data
  6921. frq = 0.0; // search using centre and top frqs of frq bins
  6922. top = dz->halfchwidth;
  6923. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) { //RWD was vc+2
  6924. if(top < srchbot) {
  6925. subfrq = frq; // Remember chan-frq and number of the channel before fundamental (should be) found
  6926. subchan = cc;
  6927. } else if(frq < srchtop) { // For any channel in range, find channel-centre closest to fundamental
  6928. if(fabs(thepitch - frq) < ferror) {
  6929. ferror = fabs(thepitch - frq);
  6930. *newcc = cc;
  6931. }
  6932. } else if(ferror == HUGE) { // If no frequencies within range of fundamental (should be impossible!!), keep closest
  6933. if(fabs(frq - thepitch) < fabs(thepitch - subfrq))
  6934. *newcc = cc; // If chan-frq above searched-for range is closer than one below, use its channel
  6935. else
  6936. *newcc = subchan; // else use channel below
  6937. break;
  6938. }
  6939. frq += dz->chwidth;
  6940. top += dz->chwidth;
  6941. }
  6942. } else { // Normal case
  6943. fundamp = -HUGE;
  6944. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  6945. frq = dz->flbufptr[0][FREQ];
  6946. if(frq < srchbot) {
  6947. subfrq = frq; // Remember frq and channo in channel before fundamental (should be) found
  6948. subchan = cc;
  6949. } else if(frq < srchtop) {
  6950. if(dz->flbufptr[0][AMPP] > fundamp) { // If (frqs near) fundamental found, find loudest occurence
  6951. fundamp = dz->flbufptr[0][AMPP];
  6952. *newcc = cc;
  6953. }
  6954. } else if(fundamp == -HUGE) { // If no frequencies within range of fundamental, keep closest in frq
  6955. if(subfrq == HUGE)
  6956. *newcc = cc; // If there is no subfrq, use the frq in chan above range
  6957. if(fabs(frq - thepitch) < fabs(thepitch - subfrq))
  6958. *newcc = cc; // If frq above is closer than one below, use its channel
  6959. else
  6960. *newcc = subchan; // else use channel below
  6961. break;
  6962. }
  6963. }
  6964. }
  6965. return FINISHED;
  6966. }
  6967. /************************************ CONTINUITY_SMOOTHING ***************************/
  6968. int continuity_smoothing(dataptr dz)
  6969. {
  6970. double *running_average = dz->parray[RUNNINGAVRG];
  6971. double *runavdur = dz->parray[RUNAVGDURS];
  6972. int *avstart = dz->lparray[AVSTT];
  6973. int runavcnt = 0, lastrunavcnt, n, maxavg, ahead, behind, bracketed, thisbracketed;
  6974. double ratio, maxtime, bracketdur = 0.0;
  6975. int done;
  6976. memset((char *)running_average,0,dz->wlength * sizeof(double));
  6977. memset((char *)runavdur,0,dz->wlength * sizeof(double));
  6978. memset((char *)avstart,0,dz->wlength * sizeof(int));
  6979. // FIND BLOCKS WHOSE RUNNING AVERAGES DIFFER
  6980. for(n = 0; n < dz->wlength;n++) {
  6981. if(dz->pitches[n] < 0.0) // Don't weigh time of non-pitch areas
  6982. continue;
  6983. if(running_average[runavcnt] == 0.0) { // First running average will not have a start value
  6984. avstart[runavcnt] = n;
  6985. running_average[runavcnt] = dz->pitches[n];
  6986. } else {
  6987. if(dz->pitches[n] > running_average[runavcnt])
  6988. ratio = dz->pitches[n]/running_average[runavcnt];
  6989. else
  6990. ratio = running_average[runavcnt]/dz->pitches[n];
  6991. if(ratio < ALMOST_TWO) // If next pitch is close to running-average, continue to average, and sum duration
  6992. running_average[runavcnt] = (running_average[runavcnt] + dz->pitches[n])/2;
  6993. else { // IF not, start a new average
  6994. runavcnt++;
  6995. avstart[runavcnt] = n;
  6996. running_average[runavcnt] = dz->pitches[n];
  6997. }
  6998. }
  6999. runavdur[runavcnt] += dz->frametime;
  7000. }
  7001. runavcnt++;
  7002. if(runavcnt < 2)
  7003. return FINISHED;
  7004. lastrunavcnt = runavcnt;
  7005. do {
  7006. // FIND THE LONGEST BLOCK (Aread with no apparent pitch are not counted)
  7007. maxtime = 0.0;
  7008. maxavg = 0;
  7009. for(n = 0;n<runavcnt;n++) {
  7010. if(runavdur[n] > maxtime) {
  7011. maxtime = runavdur[n];
  7012. maxavg = n;
  7013. }
  7014. }
  7015. // WORKING OUTWARDS FROM THE LONGEST BLOCK, ELIMINATE BLOCKS WHICH ARE SUDDENLY DIFFERENT, FOR TOO SHORT A TIME
  7016. if(maxavg < runavcnt-2) {
  7017. for(n = maxavg; n < runavcnt;n++) { // working upwards from the most persistent average
  7018. ahead = n+2; // find if the bracketing bloks of the next blok have similar average
  7019. bracketed = n+1;
  7020. if(ahead >= runavcnt)
  7021. break;
  7022. bracketdur = 0.0;
  7023. done = 0;
  7024. if(running_average[n] > running_average[ahead])
  7025. ratio = running_average[n]/running_average[ahead];
  7026. else
  7027. ratio = running_average[ahead]/running_average[n];
  7028. bracketdur = runavdur[bracketed];
  7029. if(ratio < ALMOST_TWO) { // If 2 bracketing averages are similar
  7030. if (runavdur[bracketed] < TOO_SHORT_PICH) { // & intervening block is short
  7031. averages_smooth(bracketed,n,runavcnt,dz); // Smooth the intervening block
  7032. n++; // and skip over the intervening (smoothed) block, and continue
  7033. } else
  7034. continue; // But if not short, proceed normally along the array
  7035. } else { // If 2 bracketing averages are not similar,
  7036. while(runavdur[bracketed]<TOO_SHORT_PICH) { // we have at least 3 contiguous but different averages
  7037. ahead++; // proceed to wider bracket
  7038. bracketed++;
  7039. if(ahead >= runavcnt) { // until we find a matching pair of bracketing averages
  7040. done = 1;
  7041. break;
  7042. }
  7043. bracketdur += runavdur[bracketed];
  7044. if(bracketdur > TOO_SHORT_PICH) // If total duration of bracketed items no longer short, go back to outer loop
  7045. break;
  7046. if(running_average[n] > running_average[ahead])
  7047. ratio = running_average[n]/running_average[ahead];
  7048. else
  7049. ratio = running_average[ahead]/running_average[n];
  7050. if(ratio < ALMOST_TWO) { // If we finally find a valid outer bracket
  7051. // (Total duration of things within bracket is still very short)
  7052. for(thisbracketed = n+1;thisbracketed < ahead;thisbracketed++)
  7053. averages_smooth(thisbracketed,n,runavcnt,dz); // Smooth ALL the intervening block
  7054. n += (ahead-n)-1; // We want to advance to "ahead": loop will force advance of 1.
  7055. break;
  7056. } // so advance here by distance from n to ahead (= ahead-n) minus 1
  7057. } // Otherwise we have found yet another non-matching block
  7058. } // continue to assemble bracketed items
  7059. if(done)
  7060. break;
  7061. }
  7062. } else // Either maxavg is at the v. end (so no end to check)
  7063. n = maxavg; // Or it is at the penultimate position, so need to check last blok
  7064. // CHECK THE LAST BLOCK, IF NOT ALREADY CHECKED
  7065. if(n == runavcnt-2) {
  7066. bracketed = n+1;
  7067. if(running_average[bracketed] > running_average[n])
  7068. ratio = running_average[bracketed]/running_average[n];
  7069. else
  7070. ratio = running_average[n]/running_average[bracketed];
  7071. if(ratio < ALMOST_TWO && runavdur[bracketed] < TOO_SHORT_PICH)
  7072. averages_smooth(bracketed,n,runavcnt,dz);
  7073. }
  7074. // NOW PROCEED BACKWARDS FROM LONGEST BLOK
  7075. if(maxavg > 1) {
  7076. for(n = maxavg; n >= 0; n--) { // working backwards from the most persistent average
  7077. behind = n-2;
  7078. bracketed = n-1;
  7079. if(behind < 0)
  7080. break;
  7081. bracketdur = 0.0;
  7082. done = 0;
  7083. if(running_average[n] > running_average[behind])
  7084. ratio = running_average[n]/running_average[behind];
  7085. else
  7086. ratio = running_average[behind]/running_average[n];
  7087. if(ratio < ALMOST_TWO) { // If 2 bracketing averages are similar
  7088. if(runavdur[bracketed] < TOO_SHORT_PICH) { // & intervening block is short
  7089. averages_smooth(bracketed,n,runavcnt,dz); // Smooth the intervening block
  7090. n--; // and skip over the intervening (smoothed) block, and continue
  7091. } else
  7092. continue; // But if not short, proceed normally along the array
  7093. } else { // If 2 bracketing averages are not similar,
  7094. while(runavdur[bracketed]<TOO_SHORT_PICH) { // we have at least 3 contiguous but different averages
  7095. behind--; // proceed to wider bracket
  7096. bracketed--;
  7097. if(behind <= 0) { // until we find a matching pair of bracketing averages
  7098. done = 1;
  7099. break;
  7100. }
  7101. bracketdur += runavdur[bracketed];
  7102. if(bracketdur > TOO_SHORT_PICH) // If total duration of bracketed items no loner short, go back to outer loop
  7103. break;
  7104. if(running_average[n] > running_average[behind])
  7105. ratio = running_average[n]/running_average[behind];
  7106. else
  7107. ratio = running_average[behind]/running_average[n];
  7108. if(ratio < ALMOST_TWO) { // If we finally find a valid outer bracket
  7109. // (Total duration of things within bracket is still very short)
  7110. for(thisbracketed = n-1;thisbracketed > behind;thisbracketed--)
  7111. averages_smooth(thisbracketed,n,runavcnt,dz); // Smooth ALL the intervening block
  7112. n -= (n-behind)-1; // We want to regress to "behind": loop will force regress of 1, so advance here by "ahead-1"
  7113. break; // so regress here by distance from n to behind (= n-behind) minus 1
  7114. } // ang go back to outer loop
  7115. } // Otherwise we have found yet another non-matching block
  7116. } // continue to assemble bracketed items
  7117. if(done)
  7118. break;
  7119. }
  7120. }
  7121. // CHECK THE FIRST BLOCK IF NESS
  7122. if(n == 1) {
  7123. bracketed = 0;
  7124. if(running_average[bracketed] > running_average[n])
  7125. ratio = running_average[bracketed]/running_average[n];
  7126. else
  7127. ratio = running_average[n]/running_average[bracketed];
  7128. if(ratio < ALMOST_TWO && runavdur[bracketed] < TOO_SHORT_PICH)
  7129. averages_smooth(bracketed,n,runavcnt,dz);
  7130. }
  7131. // NOW RECURSIVELY SMOOTH ON NEW VALUES UNTIL NO MORE SMOOTHING POSSIBLE
  7132. memset((char *)running_average,0,dz->wlength * sizeof(double));
  7133. memset((char *)runavdur,0,dz->wlength * sizeof(double));
  7134. memset((char *)avstart,0,dz->wlength * sizeof(int));
  7135. lastrunavcnt = runavcnt;
  7136. runavcnt = 0;
  7137. for(n = 0; n < dz->wlength;n++) {
  7138. if(dz->pitches[n] < 0.0)
  7139. continue;
  7140. if(running_average[runavcnt] == 0.0) {
  7141. avstart[runavcnt] = n;
  7142. running_average[runavcnt] = dz->pitches[n];
  7143. } else {
  7144. if(dz->pitches[n] > running_average[runavcnt])
  7145. ratio = dz->pitches[n]/running_average[runavcnt];
  7146. else
  7147. ratio = running_average[runavcnt]/dz->pitches[n];
  7148. if(ratio < ALMOST_TWO)
  7149. running_average[runavcnt] = (running_average[runavcnt] + dz->pitches[n])/2;
  7150. else {
  7151. runavcnt++;
  7152. avstart[runavcnt] = n;
  7153. running_average[runavcnt] = dz->pitches[n];
  7154. }
  7155. }
  7156. runavdur[runavcnt] += dz->frametime;
  7157. }
  7158. runavcnt++;
  7159. if(runavcnt < 2)
  7160. break;
  7161. } while(runavcnt < lastrunavcnt);
  7162. return FINISHED;
  7163. }
  7164. /************************************ AVERAGES_SMOOTH ***************************/
  7165. int averages_smooth(int bracketed,int bracket,int runavcnt,dataptr dz)
  7166. {
  7167. double new_running_average, ratio, newratio;
  7168. int k, avend;
  7169. int *avstart = dz->lparray[AVSTT];
  7170. double *running_average = dz->parray[RUNNINGAVRG];
  7171. if(bracketed+1 == runavcnt)
  7172. avend = dz->wlength;
  7173. else
  7174. avend = avstart[bracketed+1];
  7175. if(running_average[bracketed] > running_average[bracket]) { // If bracketed material too high
  7176. do {
  7177. new_running_average = 0.0;
  7178. for(k = avstart[bracketed]; k < avend;k++) {
  7179. if(dz->pitches[k] > 0.0) { // 8va transpose-down the bracketed material
  7180. dz->pitches[k] /= 2.0;
  7181. if(new_running_average == 0.0)
  7182. new_running_average = dz->pitches[k];
  7183. else
  7184. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7185. }
  7186. }
  7187. if(new_running_average > running_average[bracket]) { // If we're still higher than the goal
  7188. ratio = new_running_average/running_average[bracket];
  7189. if(ratio < ALMOST_TWO) { // But we're now in acceptable range
  7190. new_running_average = 0.0;
  7191. for(k = avstart[bracketed]; k < avend;k++) { // try the next 8va down
  7192. if(dz->pitches[k] > 0.0) {
  7193. dz->pitches[k] /= 2.0;
  7194. if(new_running_average == 0.0)
  7195. new_running_average = dz->pitches[k];
  7196. else
  7197. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7198. }
  7199. }
  7200. if(new_running_average > running_average[bracket])
  7201. newratio = new_running_average/running_average[bracket];
  7202. else
  7203. newratio = running_average[bracket]/new_running_average;
  7204. if(newratio > ratio) { // if the new material is further away from the goal than originally
  7205. for(k = avstart[bracketed]; k < avend;k++) {
  7206. if(dz->pitches[k] > 0.0)
  7207. dz->pitches[k] *= 2.0; // restore to original 8va
  7208. }
  7209. }
  7210. break; // Now quit with new pitch
  7211. }
  7212. } else // Else we.re mow lower than the goal, so at nearest
  7213. break; //
  7214. } while(ratio > ALMOST_TWO);
  7215. } else { // Else bracketed material is too low
  7216. do {
  7217. new_running_average = 0.0;
  7218. for(k = avstart[bracketed]; k < avend;k++) {
  7219. if(dz->pitches[k] > 0.0) {
  7220. dz->pitches[k] *= 2.0; // 8va transpose-up the bracketed material
  7221. if(new_running_average == 0.0)
  7222. new_running_average = dz->pitches[k];
  7223. else
  7224. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7225. }
  7226. }
  7227. if(new_running_average < running_average[bracket]) { // If we're still lower than the goal
  7228. ratio = running_average[bracket]/new_running_average;
  7229. if(ratio < ALMOST_TWO) { // But we're now in acceptable range
  7230. new_running_average = 0.0;
  7231. for(k = avstart[bracketed]; k < avend;k++) {
  7232. if(dz->pitches[k] > 0.0) {
  7233. dz->pitches[k] *= 2.0; // try the next 8va up
  7234. if(new_running_average == 0.0)
  7235. new_running_average = dz->pitches[k];
  7236. else
  7237. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7238. }
  7239. }
  7240. if(new_running_average > running_average[bracket])
  7241. newratio = new_running_average/running_average[bracket];
  7242. else
  7243. newratio = running_average[bracket]/new_running_average;
  7244. if(newratio > ratio) { // if the new material is further away from the goal than originally
  7245. for(k = avstart[bracketed]; k < avend;k++) {
  7246. if(dz->pitches[k] > 0.0)
  7247. dz->pitches[k] /= 2.0; // restore to original 8va
  7248. }
  7249. }
  7250. break;
  7251. }
  7252. } else // Else we.re now higher than the goal, so at nearest
  7253. break;
  7254. } while(ratio > ALMOST_TWO);
  7255. }
  7256. return FINISHED;
  7257. }
  7258. /************************************ EXCLUDE_NON_HARMONICS ***************************/
  7259. int exclude_non_harmonics(dataptr dz)
  7260. {
  7261. dz->xclude_nonh = 0;
  7262. switch(dz->mode) {
  7263. case(F_NARROW): if(dz->vflag[NRW_XNH]) dz->xclude_nonh = 1; break;
  7264. case(F_SQUEEZE): if(dz->vflag[SQZ_XNH]) dz->xclude_nonh = 1; break;
  7265. case(F_NEGATE): if(dz->vflag[NEG_XNH]) dz->xclude_nonh = 1; break;
  7266. case(F_MOVE): if(dz->vflag[MOV_XNH]) dz->xclude_nonh = 1; break;
  7267. case(F_MOVE2): if(dz->vflag[MOV2_XNH]) dz->xclude_nonh = 1; break;
  7268. case(F_INVERT): if(dz->vflag[INVERT_XNH]) dz->xclude_nonh = 1; break;
  7269. case(F_ROTATE): if(dz->vflag[ROTATE_XNH]) dz->xclude_nonh = 1; break;
  7270. case(F_SUPPRESS): if(dz->vflag[SUPPRESS_XNH]) dz->xclude_nonh = 1; break;
  7271. case(F_ARPEG): // fall thro
  7272. case(F_OCTSHIFT): // fall thro
  7273. case(F_TRANS): // fall thro
  7274. case(F_FRQSHIFT): // fall thro
  7275. case(F_RESPACE): // fall thro
  7276. case(F_PINVERT): // fall thro
  7277. case(F_PEXAGG): // fall thro
  7278. case(F_PQUANT): // fall thro
  7279. case(F_PCHRAND): // fall thro
  7280. case(F_RAND): if(dz->vflag[RECOLOR_XNH]) dz->xclude_nonh = 1; break;
  7281. }
  7282. if(dz->xclude_nonh) {
  7283. if((dz->fptr[HMNICBOUNDS] = (float *)malloc(10 * sizeof(float)))==NULL) {
  7284. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonic peak boundaries.\n");
  7285. return(MEMORY_ERROR);
  7286. }
  7287. }
  7288. return FINISHED;
  7289. }
  7290. /************************************ ZERO_NON_PARTIALS ***************************/
  7291. #define ABOVE_NYQUIST 0
  7292. int channel_holds_harmonic(float the_fundamental,float frq,int cc,int *top_hno,dataptr dz)
  7293. {
  7294. float *harmbounds = dz->fptr[HMNICBOUNDS], this_harmonic_frq, lobnd, upbnd;
  7295. int mid = 3, bndpairscnt = 5, boundscnt = bndpairscnt * 2;
  7296. int k, hno, lower, upper;
  7297. if(cc == 0) {
  7298. hno = 1;
  7299. for(k=0,lower=0,upper=1;k < bndpairscnt;k++,lower+=2,upper+=2) {
  7300. this_harmonic_frq = (float)(the_fundamental * hno); // lo1 hi1 lo2 hi2 lo3 hi3 lo4 hi4 lo5 hi5
  7301. lobnd = (float)(this_harmonic_frq * SEMITONE_DOWN); // | | | | | | | | | |
  7302. upbnd = (float)(this_harmonic_frq * SEMITONE_INTERVAL); // 0 1 2 3 4 5 6 7 8 9
  7303. harmbounds[lower] = lobnd;
  7304. harmbounds[upper] = upbnd;
  7305. hno++;
  7306. }
  7307. *top_hno = bndpairscnt;
  7308. }
  7309. if(frq > harmbounds[mid])
  7310. if(shufflup_harmonics_bounds(top_hno,the_fundamental,boundscnt,dz)== ABOVE_NYQUIST)
  7311. return 0;
  7312. for(k=0,hno = 1,lower=0,upper=1;k < bndpairscnt;k++,hno++,lower+=2,upper+=2) {
  7313. if(frq > harmbounds[lower]) {
  7314. if(frq < harmbounds[upper]) // Within frq bounds of a harmonic
  7315. return 1;
  7316. if(lower < boundscnt - 2) {
  7317. if(frq < harmbounds[lower+2]) { // Outside frq bounds of a harmonic
  7318. return 0;
  7319. }
  7320. } else { // Outside top harmonic boUnds
  7321. if(shufflup_harmonics_bounds(top_hno,the_fundamental,boundscnt,dz)==ABOVE_NYQUIST)
  7322. return 0; // get next harmonic, and its bounds
  7323. k--;
  7324. lower -= 2;
  7325. upper -= 2;
  7326. }
  7327. }
  7328. }
  7329. return 0; // SHOULD BE "NOT REACHED" !!!
  7330. }
  7331. /************************************ SHUFFLUP_HARMONICS_BOUNDS ***************************/
  7332. int shufflup_harmonics_bounds(int *top_hno,float the_fundamental,int boundscnt,dataptr dz)
  7333. {
  7334. float *harmbounds = dz->fptr[HMNICBOUNDS];
  7335. float this_harmonic_frq, lobnd, upbnd;
  7336. int k;
  7337. (*top_hno)++; // lo2 hi2 lo3 hi3 lo4 hi4 lo5 hi5
  7338. this_harmonic_frq = (float)the_fundamental * (*top_hno);// | | | | | | | | | |
  7339. for(k=2;k < boundscnt;k++) // 0 1 2 3 4 5 6 7 8 9
  7340. harmbounds[k-2] = harmbounds[k];
  7341. if(harmbounds[0] > dz->nyquist)
  7342. return ABOVE_NYQUIST;
  7343. lobnd = (float)(this_harmonic_frq * SEMITONE_DOWN); // Insert boundaries of next harmonic
  7344. upbnd = (float)(this_harmonic_frq * SEMITONE_INTERVAL); // lo2 hi2 lo3 hi3 lo4 hi4 lo5 hi5 lo6 hi6
  7345. harmbounds[boundscnt - 2] = lobnd; // | | | | | | | | | |
  7346. harmbounds[boundscnt - 1] = upbnd; // 0 1 2 3 4 5 6 7 8 9
  7347. return 1;
  7348. }
  7349. /***************************************** INITIALISE_CONTOURENV ***************************/
  7350. int initialise_contourenv(int *contourcnt,int contour_halfbands_per_step,dataptr dz)
  7351. {
  7352. int arraycnt, contourbands;
  7353. double frqstep, thisfrq, nextfrq;
  7354. int k = 0;
  7355. contourbands = (int)ceil(dz->clength / (contour_halfbands_per_step / 2));
  7356. arraycnt = contourbands + 2;
  7357. if((dz->fptr[CONTOURFRQ] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7358. sprintf(errstr,"INSUFFICIENT MEMORY for contour frq array.\n");
  7359. return(MEMORY_ERROR);
  7360. }
  7361. if((dz->fptr[CONTOURPCH] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7362. sprintf(errstr,"INSUFFICIENT MEMORY for contour pitch array.\n");
  7363. return(MEMORY_ERROR);
  7364. }
  7365. /*RWD zero the data */
  7366. memset((char *)dz->fptr[CONTOURPCH],0,arraycnt * sizeof(float));
  7367. if((dz->fptr[CONTOURAMP] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7368. sprintf(errstr,"INSUFFICIENT MEMORY for contour amplitude array.\n");
  7369. return(MEMORY_ERROR);
  7370. }
  7371. if((dz->fptr[CONTOURTOP] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7372. sprintf(errstr,"INSUFFICIENT MEMORY for contour frq limit array.\n");
  7373. return(MEMORY_ERROR);
  7374. }
  7375. if((dz->fptr[CONTOURAMP2] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7376. sprintf(errstr,"INSUFFICIENT MEMORY for contour amplitude array.\n");
  7377. return(MEMORY_ERROR);
  7378. }
  7379. dz->fptr[CONTOURAMP][0] = (float)0.0;
  7380. dz->fptr[CONTOURFRQ][0] = (float)1.0;
  7381. dz->fptr[CONTOURPCH][0] = (float)log10(dz->fptr[CONTOURFRQ][0]);
  7382. dz->fptr[CONTOURTOP][0] = (float)dz->halfchwidth;
  7383. frqstep = dz->halfchwidth * (double)contour_halfbands_per_step;
  7384. thisfrq = dz->fptr[CONTOURTOP][0];
  7385. k = 1;
  7386. while((nextfrq = thisfrq + frqstep) < dz->nyquist) {
  7387. if(k >= arraycnt) {
  7388. sprintf(errstr,"Formant array too small: when setting the contour frqs\n");
  7389. return(PROGRAM_ERROR);
  7390. }
  7391. dz->fptr[CONTOURFRQ][k] = (float)nextfrq;
  7392. dz->fptr[CONTOURPCH][k] = (float)log10(dz->fptr[CONTOURFRQ][k]);
  7393. dz->fptr[CONTOURTOP][k] = (float)min(dz->nyquist,nextfrq);
  7394. thisfrq = nextfrq;
  7395. k++;
  7396. }
  7397. dz->fptr[CONTOURFRQ][k] = (float)dz->nyquist;
  7398. dz->fptr[CONTOURPCH][k] = (float)log10(dz->nyquist);
  7399. dz->fptr[CONTOURTOP][k] = (float)dz->nyquist;
  7400. dz->fptr[CONTOURAMP][k] = (float)0.0;
  7401. k++;
  7402. *contourcnt = k;
  7403. return(FINISHED);
  7404. }
  7405. /**************************** GETCONTOURAMP *************************/
  7406. int getcontouramp(double *thisamp,int contourcnt,double thisfrq,dataptr dz)
  7407. {
  7408. double pp, ratio, ampdiff;
  7409. float *contourpch = dz->fptr[CONTOURPCH], *contouramp = dz->fptr[CONTOURAMP];
  7410. int z = 1;
  7411. if(thisfrq<0.0) { /* NOT SURE THIS IS CORRECT */
  7412. *thisamp = 0.0; /* SHOULD WE PHASE INVERT & RETURN A -ve AMP ?? */
  7413. return(FINISHED);
  7414. }
  7415. if(thisfrq<=1.0)
  7416. pp = 0.0;
  7417. else
  7418. pp = log10(thisfrq);
  7419. while(contourpch[z] < pp){
  7420. z++;
  7421. /*RWD may need to trap on size of array? */
  7422. if(z == contourcnt - 1)
  7423. break;
  7424. }
  7425. ratio = (pp - contourpch[z-1])/(contourpch[z] - contourpch[z-1]);
  7426. ampdiff = contouramp[z] - contouramp[z-1];
  7427. *thisamp = contouramp[z-1] + (ampdiff * ratio);
  7428. *thisamp = max(0.0,*thisamp);
  7429. return(FINISHED);
  7430. }
  7431. /**************************** GETCONTOURAMP2 *************************/
  7432. int getcontouramp2(double *thisamp,int contourcnt,double thisfrq,dataptr dz)
  7433. {
  7434. double pp, ratio, ampdiff;
  7435. float *contourpch = dz->fptr[CONTOURPCH], *contouramp2 = dz->fptr[CONTOURAMP2];
  7436. int z = 1;
  7437. if(thisfrq<0.0) { /* NOT SURE THIS IS CORRECT */
  7438. *thisamp = 0.0; /* SHOULD WE PHASE INVERT & RETURN A -ve AMP ?? */
  7439. return(FINISHED);
  7440. }
  7441. if(thisfrq<=1.0)
  7442. pp = 0.0;
  7443. else
  7444. pp = log10(thisfrq);
  7445. while(contourpch[z] < pp){
  7446. z++;
  7447. /*RWD may need to trap on size of array? */
  7448. if(z == contourcnt - 1)
  7449. break;
  7450. }
  7451. ratio = (pp - contourpch[z-1])/(contourpch[z] - contourpch[z-1]);
  7452. ampdiff = contouramp2[z] - contouramp2[z-1];
  7453. *thisamp = contouramp2[z-1] + (ampdiff * ratio);
  7454. *thisamp = max(0.0,*thisamp);
  7455. return(FINISHED);
  7456. }
  7457. /*********************** REMEMBER_CONTOURAMP ****************/
  7458. int remember_contouramp(int contourcnt,dataptr dz)
  7459. {
  7460. int n;
  7461. float *contouramp2 = dz->fptr[CONTOURAMP2], *contouramp = dz->fptr[CONTOURAMP];
  7462. if(contouramp2 == NULL) {
  7463. sprintf(errstr,"Contour amp 2nd array has not been mallocd.\n");
  7464. return PROGRAM_ERROR;
  7465. }
  7466. for(n = 0;n < contourcnt;n++)
  7467. contouramp2[n] = contouramp[n];
  7468. return FINISHED;
  7469. }
  7470. /********************** EXTRACT_CONTOUR *******************/
  7471. #define CHAN_SRCHRANGE_F (4)
  7472. int extract_contour(int contourcnt,dataptr dz)
  7473. {
  7474. int n, cc, vc, contourcnt_less_one;
  7475. int botchan, topchan;
  7476. double botfreq, topfreq;
  7477. double bwidth_in_chans;
  7478. float *contouramp = dz->fptr[CONTOURAMP];
  7479. memset((char *)contouramp,0,contourcnt * sizeof(float));
  7480. contourcnt_less_one = contourcnt - 1;
  7481. vc = 0;
  7482. for(n=0;n<contourcnt;n++)
  7483. contouramp[n] = (float)0.0;
  7484. topfreq = 0.0f;
  7485. n = 0;
  7486. while(n < contourcnt_less_one) {
  7487. botfreq = topfreq;
  7488. botchan = (int)((botfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  7489. botchan -= CHAN_SRCHRANGE_F;
  7490. botchan = max(botchan,0);
  7491. topfreq = dz->specenvtop[n];
  7492. topchan = (int)((topfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  7493. topchan += CHAN_SRCHRANGE_F;
  7494. topchan = min(topchan,dz->clength);
  7495. for(cc = botchan,vc = botchan * 2; cc < topchan; cc++,vc += 2) {
  7496. if(dz->flbufptr[0][FREQ] >= botfreq && dz->flbufptr[0][FREQ] < topfreq)
  7497. contouramp[n] = (float)(contouramp[n] + dz->flbufptr[0][AMPP]);
  7498. }
  7499. bwidth_in_chans = (double)(topfreq - botfreq)/dz->chwidth;
  7500. contouramp[n] = (float)(contouramp[n]/bwidth_in_chans);
  7501. n++;
  7502. }
  7503. return(FINISHED);
  7504. }
  7505. /************************************ SUPPRESS_HARMONICS ***************************/
  7506. int suppress_harmonics(dataptr dz)
  7507. {
  7508. int suppress_h = 0;
  7509. switch(dz->mode) {
  7510. case(F_MOVE): if(dz->vflag[MOV_KHM]) suppress_h = 1; break;
  7511. case(F_MOVE2): if(dz->vflag[MOV2_KHM]) suppress_h = 1; break;
  7512. case(F_NEGATE): if(dz->vflag[NEG_KHM]) suppress_h = 1; break;
  7513. case(F_INVERT): if(dz->vflag[INVERT_KHM]) suppress_h = 1; break;
  7514. case(F_NARROW): if(dz->vflag[NRW_KHM]) suppress_h = 1; break;
  7515. case(F_SQUEEZE):if(dz->vflag[SQZ_KHM]) suppress_h = 1; break;
  7516. case(F_ROTATE): if(dz->vflag[ROTATE_KHM]) suppress_h = 1; break;
  7517. }
  7518. if(suppress_h && dz->fptr[HMNICBOUNDS] == NULL) {
  7519. if((dz->fptr[HMNICBOUNDS] = (float *)malloc(10 * sizeof(float)))==NULL) {
  7520. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonic peak boundaries.\n");
  7521. return(MEMORY_ERROR);
  7522. }
  7523. }
  7524. return FINISHED;
  7525. }
  7526. /************************************ TROF_DETECT ***************************/
  7527. int trof_detect(dataptr dz) // DOESN'T WORK will have to do it BY HAND : Need a SLOOM AP TO HELP !!!
  7528. {
  7529. double *level = dz->parray[P_PRETOTAMP];
  7530. double lev, lastlev = 0.0, maxlevel, rise, endtroftime, endtrofgap, maxval;
  7531. double lastpeak, lastlastpeak, pk_to_pre_trof, pk_to_post_trof;
  7532. int n, tim, val, lasttim, lastval, up_cnt = 0, dn_cnt = 0, trofcnt = 0, lasttrofcnt, endtrofat, lasttrofat, thistrofat = 0, thispeak;
  7533. int k;
  7534. double *trof;
  7535. if((trof = (double *)malloc(dz->wlength * 2 * sizeof(float)))==NULL) {
  7536. sprintf(errstr,"INSUFFICIENT MEMORY to store trof times.\n");
  7537. return(MEMORY_ERROR);
  7538. }
  7539. // Establish maximum level
  7540. maxlevel = 0.0;
  7541. for(n=0;n<dz->wlength;n++)
  7542. maxlevel = max(maxlevel,level[n]);
  7543. // Find troughs, ensuring intervening peaks are sufficiently prominent
  7544. lastpeak = -1.0;
  7545. lastlastpeak = -1.0;
  7546. pk_to_pre_trof = -1.0;
  7547. for(n=0;n<dz->wlength;n++) {
  7548. lev = level[n]/maxlevel;
  7549. rise = lev - lastlev;
  7550. if(rise > 0.0) {
  7551. if(dn_cnt > 0) {
  7552. trof[trofcnt++] = dz->frametime * (n-1);
  7553. trof[trofcnt++] = lastlev;
  7554. if(pk_to_pre_trof > 0.0) { // If previous peak-after-a-trof exists
  7555. pk_to_post_trof = lastpeak - trof[trofcnt-1];
  7556. if(lastpeak < dz->fsil_ratio || // If the peak is not absolutely loud enough
  7557. (pk_to_pre_trof < MIN_PEAKTROF_GAP // OR the peak is not high enough above either bracketing trof
  7558. && pk_to_post_trof < MIN_PEAKTROF_GAP)) {
  7559. if(trof[trofcnt-3] < trof[trofcnt-3]) // If previous trof lower than this
  7560. trofcnt -= 2; // overwrite this one
  7561. else { // else
  7562. for(k = trofcnt-2;k< trofcnt;k++) // overwrite last trof
  7563. trof[k-2] = trof[k];
  7564. trofcnt -= 2;
  7565. }
  7566. lastpeak = lastlastpeak; // lastpeak ignored: penultimate peak is now "lastpeak"
  7567. }
  7568. }
  7569. dn_cnt = 0;
  7570. up_cnt = 0;
  7571. }
  7572. up_cnt++;
  7573. } else {
  7574. if(up_cnt > 0) {
  7575. lastlastpeak = lastpeak; // remember this peak and the peak before it
  7576. lastpeak = lastlev; //
  7577. if(trofcnt) // If a prior trof exists, calc ratio of pk to prior trof
  7578. pk_to_pre_trof = lastpeak - trof[trofcnt-1];
  7579. dn_cnt = 0;
  7580. up_cnt = 0;
  7581. }
  7582. dn_cnt++;
  7583. }
  7584. lastlev = lev;
  7585. }
  7586. // Eliminate too close trofs
  7587. lasttim = 0;
  7588. lastval = 1;
  7589. lasttrofcnt = trofcnt;
  7590. for(tim=2,val=3;tim<trofcnt;tim+=2,val+=2) {
  7591. if(trof[tim] - trof[lasttim] < MIN_SYLLAB_DUR) {
  7592. if(trof[val] <= trof[lastval]) {
  7593. k = tim; // overwrite previous trof
  7594. while(k < trofcnt) {
  7595. trof[k-2] = trof[k];
  7596. k++;
  7597. }
  7598. } else {
  7599. k = tim + 2; // overwrite current trof
  7600. while(k < trofcnt) {
  7601. trof[k-2] = trof[k];
  7602. k++;
  7603. }
  7604. }
  7605. val -= 2;
  7606. tim -= 2;
  7607. trofcnt -= 2;
  7608. } else {
  7609. lasttim += 2;
  7610. lastval += 2;
  7611. }
  7612. }
  7613. endtroftime = 0.0;
  7614. for(n=dz->wlength-1;n>=0;n--) {
  7615. if(level[n] > dz->fsil_ratio) {
  7616. endtroftime = (n+1) * dz->frametime;
  7617. if(endtroftime > 0.0) {
  7618. endtrofgap = endtroftime - trof[trofcnt-2];
  7619. if(endtrofgap > 0.0) {
  7620. endtrofat = n+1;
  7621. lasttrofat = (int)round(trof[trofcnt-2]/dz->frametime);
  7622. maxval = 0.0;
  7623. for(k=lasttrofat;k<endtrofat;k++)
  7624. maxval = max(maxval,level[k]/maxlevel);
  7625. if(maxval - trof[trofcnt-1] < dz->fsil_ratio)
  7626. trof[trofcnt-2] = endtroftime;
  7627. }
  7628. }
  7629. break;
  7630. }
  7631. }
  7632. if(dz->vflag[PKS_ONLY] || dz->vflag[PKS_TROFS]) {
  7633. for(n = 2;n < trofcnt;n+=2) {
  7634. if(n==2)
  7635. lasttrofat = (int)round(trof[n-2]/dz->frametime); // Trof times, converted to window nums
  7636. else
  7637. lasttrofat = thistrofat;
  7638. thistrofat = (int)round(trof[n]/dz->frametime);
  7639. maxlevel = trof[n-1];
  7640. thispeak = lasttrofat;
  7641. for(k = lasttrofat;k < thistrofat;k++) { // Amplitude levels
  7642. if(level[k] > maxlevel) {
  7643. thispeak = k;
  7644. maxlevel = level[k];
  7645. }
  7646. }
  7647. trof[n-1] = thispeak * dz->frametime; // Store peaktimes in place of trof level vals
  7648. }
  7649. if(dz->vflag[PKS_ONLY]) { // Peaks are in odd table locations
  7650. for(n = 1;n < trofcnt-2;n+=2)
  7651. fprintf(dz->fp,"%lf\n",trof[n]);
  7652. } else { // Trofs & peaks are in all locations
  7653. if(trof[0] != 0.0);
  7654. fprintf(dz->fp,"%lf\n",0.0); // Force trof at time zero
  7655. for(n = 0;n < trofcnt-1;n++)
  7656. fprintf(dz->fp,"%lf\n",trof[n]);
  7657. }
  7658. return FINISHED;
  7659. }
  7660. if(trof[0] != 0.0); // Force trof at time zero
  7661. fprintf(dz->fp,"%lf\n",0.0);
  7662. for(n = 0;n < trofcnt;n+=2) // Trof times are in even locations
  7663. fprintf(dz->fp,"%lf\n",trof[n]);
  7664. return FINISHED;
  7665. }
  7666. /************************************ ZERO_SPECTRUM_TOP ***************************/
  7667. void zero_spectrum_top(int cc,dataptr dz)
  7668. {
  7669. int vc = cc * 2;
  7670. for(; cc < dz->clength;cc++, vc+=2)
  7671. dz->flbufptr[0][AMPP] = 0.0f;
  7672. }
  7673. /************************************ FORMANTS_RECOLOR ***************************/
  7674. int formants_recolor(int inner_lpcnt,double *phase,int *up,int arp_param,double minpitch,double maxpitch,int contourcnt,dataptr dz)
  7675. {
  7676. int exit_status, cc, vc, newcc, do_arpegg = 0, nextup = 1, tail = 0, k;
  7677. float the_fundamental, frq, thisfrq, newfrq = 0.0, endamp = 0.0;
  7678. double frqtrans = 1.0, frqshift = 0.0, randomisation = 0.0, rand, incr;
  7679. double nextphase = 0.0, thisamp, origspecamp, newspecamp, vocode_ratio, searchfrqlimit;
  7680. int *isharm = dz->iparray[ISHARM];
  7681. double partial_number_centre, partial_number_foot, partial_number_top, arpegamp = 0.0, pre_amptotal = 0.0, post_amptotal = 0.0;
  7682. double lower_partial_number_top = 0.0, lower_partial_number_foot = 0.0, upper_partial_number_top = 0.0, upper_partial_number_foot = 0.0;
  7683. double lobandbot = 0.0, lobandtop = 0.0, hibandbot = 0.0, hibandtop = 0.0, bwidth = 0.0;
  7684. int is_split = 0, dotopfill = 0;
  7685. // Get window pitch
  7686. the_fundamental = dz->pitches[inner_lpcnt];
  7687. if(the_fundamental < 0.0) { // If unpitched and "silent" windows have been retained & this is one, silence the window
  7688. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc+=2)
  7689. dz->flbufptr[0][AMPP] = 0.0f;
  7690. *up = nextup;
  7691. *phase = nextphase;
  7692. return FINISHED;
  7693. }
  7694. // IF ARPEGGIATING : Calculate the range of the arpeggiation window
  7695. if(dz->brksize[arp_param] || dz->param[arp_param] > 0.0) {
  7696. // IF ARPEGGIATING : precalc nextphase by advancing phase according to arpeggiation-speed
  7697. nextphase = *phase + (dz->param[arp_param] * dz->phasefactor);
  7698. if(nextphase > 1.0) {
  7699. nextup = !(*up);
  7700. nextphase -= 1.0;
  7701. } else
  7702. nextup = *up;
  7703. // & calculate the range of the arpeggiation window
  7704. if(dz->vflag[RECOLOR_DWN])
  7705. partial_number_centre = (1.0 - *phase) * ARPEG_RANGE;
  7706. else if(dz->vflag[RECOLOR_CYC]) {
  7707. if(up)
  7708. partial_number_centre = *phase * ARPEG_RANGE;
  7709. else
  7710. partial_number_centre = (1.0 - *phase) * ARPEG_RANGE;
  7711. } else
  7712. partial_number_centre = *phase * ARPEG_RANGE;
  7713. partial_number_foot = partial_number_centre - ARPEG_WIN_HALFWIDTH;
  7714. partial_number_top = partial_number_centre + ARPEG_WIN_HALFWIDTH;
  7715. if(partial_number_top > ARPEG_RANGE) {
  7716. lower_partial_number_foot = 0.0; // NB partial numbers calculated over range 0 to 7
  7717. lower_partial_number_top = partial_number_top - ARPEG_RANGE; // But need to be in range 1-8 to multiply the fundamental
  7718. upper_partial_number_foot = partial_number_top;
  7719. upper_partial_number_top = ARPEG_RANGE;
  7720. lobandbot = (lower_partial_number_foot + 1.0) * the_fundamental;
  7721. lobandtop = (lower_partial_number_top + 1.0) * the_fundamental;
  7722. hibandbot = (upper_partial_number_foot + 1.0) * the_fundamental;
  7723. hibandtop = (upper_partial_number_top + 1.0) * the_fundamental;
  7724. is_split = 1;
  7725. } else if(partial_number_foot < 0.0) {
  7726. upper_partial_number_foot = partial_number_foot + ARPEG_RANGE;
  7727. upper_partial_number_top = ARPEG_RANGE;
  7728. lower_partial_number_foot = 0.0;
  7729. lower_partial_number_top = partial_number_top;
  7730. lobandbot = (lower_partial_number_foot + 1.0) * the_fundamental;
  7731. lobandtop = (lower_partial_number_top + 1.0) * the_fundamental;
  7732. hibandbot = (upper_partial_number_foot + 1.0) * the_fundamental;
  7733. hibandtop = (upper_partial_number_top + 1.0) * the_fundamental;
  7734. is_split = 1;
  7735. } else {
  7736. lobandbot = (partial_number_foot + 1.0) * the_fundamental;
  7737. lobandtop = (partial_number_top + 1.0) * the_fundamental;
  7738. is_split = 0;
  7739. }
  7740. bwidth = ARPEG_WIN_WIDTH * the_fundamental;
  7741. do_arpegg = 1; // and setup arpeggiation flag
  7742. }
  7743. dotopfill = 0;
  7744. if(dz->vflag[RECOLOR_FIL]) { // Attempt to fill top of spectrum, where src is shrunk in spectral range
  7745. switch(dz->mode) {
  7746. case(F_OCTSHIFT): if(dz->iparam[COLINT] < 0) dotopfill = 1; break;
  7747. case(F_FRQSHIFT): // fall thro
  7748. case(F_TRANS): if(dz->param[COLINT] < 0) dotopfill = 1; break;
  7749. case(F_RESPACE): if(dz->param[COLINT] < the_fundamental) dotopfill = 1; break;
  7750. }
  7751. }
  7752. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  7753. return(exit_status);
  7754. // initialise the extra "windowbuf"
  7755. memset((char *)dz->windowbuf[0],0,dz->wanted * sizeof(float));
  7756. // Get frq-moving value
  7757. switch(dz->mode) {
  7758. case(F_OCTSHIFT): frqtrans = pow(2.0,dz->iparam[COLINT]); break;
  7759. case(F_TRANS): frqtrans = pow(2.0,dz->param[COLFLT]/SEMITONES_PER_OCTAVE); break;
  7760. case(F_FRQSHIFT): frqshift = dz->param[COLFLT]; break;
  7761. case(F_RESPACE): frqshift = dz->param[COLFLT]; break;
  7762. case(F_RAND):
  7763. randomisation = dz->param[COLFLT];
  7764. rand = (drand48() * 2.0) - 1.0; // For rand option, generate number in range -1 TO +1 or less
  7765. rand /= 2.0; // to range +- 1/2.
  7766. rand *= randomisation; // Some value with this range, or a smaller range around centre at 0.0
  7767. frqshift = the_fundamental * rand; // Step is <= +- 1/2 distance between harmonics
  7768. break;
  7769. case(F_PINVERT):
  7770. if((exit_status = pitch_invert(&newfrq,the_fundamental,dz))<0)
  7771. return exit_status;
  7772. frqtrans = newfrq/the_fundamental;
  7773. break;
  7774. case(F_PEXAGG):
  7775. if((exit_status = exag_pitchline(&newfrq,dz->pitches[inner_lpcnt],minpitch,maxpitch,dz))<0)
  7776. return exit_status;
  7777. frqtrans = newfrq/the_fundamental;
  7778. break;
  7779. case(F_PCHRAND):// fall thro
  7780. case(F_PQUANT):
  7781. newfrq = dz->pitches2[inner_lpcnt];
  7782. frqtrans = newfrq/the_fundamental;
  7783. break;
  7784. }
  7785. // Do the frq change required, on the fundamental
  7786. switch(dz->mode) {
  7787. case(F_RESPACE): newfrq = the_fundamental; break;
  7788. case(F_OCTSHIFT): // fall thro
  7789. case(F_TRANS): newfrq = (float)(the_fundamental * frqtrans); break;
  7790. case(F_FRQSHIFT): // fall thro
  7791. case(F_RAND): newfrq = (float)min(FSPEC_MINFRQ,max((float)(the_fundamental + frqshift),dz->nyquist)); break;
  7792. case(F_ARPEG): newfrq = the_fundamental; break;
  7793. }
  7794. // If EXI flag set, (non-harmonics channels TO BE zeroed)
  7795. // Find and transpose the partials: placing them in "windowbuf"
  7796. if(dz->vflag[RECOLOR_EXI]) {
  7797. if((exit_status = find_and_change_partials(the_fundamental,newfrq,isharm,frqshift,frqtrans,randomisation,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,do_arpegg,is_split,dz))<0)
  7798. return exit_status;
  7799. // Then delete the non-partial channel data
  7800. for(cc=0,vc=0;cc < dz->clength;cc++,vc+=2) {
  7801. if(dz->windowbuf[0][FREQ] <= 0.0) {
  7802. dz->windowbuf[0][AMPP] = 0.0;
  7803. dz->windowbuf[0][FREQ] = (float)((double)cc * dz->chwidth);
  7804. }
  7805. }
  7806. // Finally, copy transformed spectrum back into flbufptr, ready for output
  7807. memcpy((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],dz->wanted * sizeof(float));
  7808. } else {
  7809. // Otherwise, modify the entire spectrum:
  7810. // First appegiate the entire spectrum (i.e. run the arpeggiation window over the entire spectrum)
  7811. if(dz->mode == F_ARPEG || do_arpegg) {
  7812. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7813. thisfrq = dz->flbufptr[0][FREQ];
  7814. if((exit_status = arpeggiate(&arpegamp,thisfrq,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,is_split,dz))<0)
  7815. return exit_status;
  7816. dz->flbufptr[0][AMPP] = (float)arpegamp;
  7817. }
  7818. }
  7819. // For transposed or shifted data, put the transformed data into "windowbuf" in the appropriate (new) channel
  7820. if(dz->mode != F_ARPEG) {
  7821. switch(dz->mode) {
  7822. case(F_OCTSHIFT): // fall thro
  7823. case(F_TRANS): // fall thro
  7824. case(F_PINVERT): // fall thro
  7825. case(F_PEXAGG): // fall thro
  7826. case(F_PQUANT): // fall thro
  7827. case(F_PCHRAND): // fall thro
  7828. case(F_FRQSHIFT):
  7829. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7830. if(dz->mode == F_FRQSHIFT)
  7831. newfrq = (float)(dz->flbufptr[0][FREQ] + frqshift); // Frqshift
  7832. else // OR
  7833. newfrq = (float)(dz->flbufptr[0][FREQ] * frqtrans); // Transpose
  7834. newcc = (int)round(newfrq/dz->chwidth); // Find appropriate new channel
  7835. if(newcc >= 0 && newcc <= dz->clength-1) { // If channel is within range
  7836. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) { // IF new data is louder than any data already copied into thus location
  7837. dz->windowbuf[0][newcc*2 + 1] = newfrq; // Copy data into windowbuf
  7838. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  7839. }
  7840. }
  7841. }
  7842. break;
  7843. case(F_RESPACE):
  7844. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7845. newfrq = dz->flbufptr[0][FREQ];
  7846. if(newfrq >= the_fundamental) { // For all data above the fundamental
  7847. newfrq -= the_fundamental; // Shrink its distance above fundamental, by ratio new-harm spacing to orig
  7848. newfrq *= (float)(frqshift/the_fundamental); // and add back onto fundamental
  7849. newfrq += the_fundamental;
  7850. }
  7851. newcc = (int)round(newfrq/dz->chwidth);
  7852. if(newcc >= 0 && newcc <= dz->clength-1) {
  7853. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) {
  7854. dz->windowbuf[0][newcc*2 + 1] = (float)(newfrq);
  7855. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  7856. }
  7857. }
  7858. }
  7859. break;
  7860. case(F_RAND):
  7861. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7862. frq = dz->flbufptr[0][FREQ];
  7863. rand = (drand48() * 2.0) - 1.0;
  7864. rand /= 2.0;
  7865. rand *= randomisation;
  7866. frqshift = the_fundamental * rand;
  7867. newfrq = (float)(dz->flbufptr[0][FREQ] + frqshift);
  7868. newcc = (int)round(newfrq/dz->chwidth);
  7869. if(newcc >= 0 && newcc <= dz->clength-1) {
  7870. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) {
  7871. dz->windowbuf[0][newcc*2 + 1] = (float)(newfrq);
  7872. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  7873. }
  7874. }
  7875. }
  7876. break;
  7877. }
  7878. if(dotopfill) {
  7879. for(cc = dz->clength-1,vc=cc*2;cc >= 0;cc--,vc-=2) {
  7880. if(dz->windowbuf[0][FREQ] > 0.0) {
  7881. endamp = dz->windowbuf[0][AMPP];
  7882. break;
  7883. }
  7884. }
  7885. dotopfill = cc+1;
  7886. if((exit_status = do_top_of_spectrum_fill(dotopfill,endamp,the_fundamental,frqtrans,frqshift,&tail,dz))<0)
  7887. return exit_status;
  7888. }
  7889. // Put a reasonable freq on channels which have not received new data (HEREH : should these remain amp zero ??)
  7890. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7891. if(dz->windowbuf[0][FREQ] == 0.0)
  7892. dz->windowbuf[0][FREQ] = (float)(cc * dz->chwidth);
  7893. }
  7894. // Extract envelope of new data, into specenvamp2
  7895. if(!(dz->mode == F_PCHRAND && dz->vflag[NO_RESHAPE])) {
  7896. dz->flbufptr[1] = dz->windowbuf[0];
  7897. if((exit_status = extract_specenv(1,1,dz))<0)
  7898. return(exit_status);
  7899. // Impose the ORIGINAL spectral envelope on the new data
  7900. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7901. frq = dz->windowbuf[0][FREQ]; // At new-spectrum channel-frq
  7902. if((exit_status = getspecenvamp(&newspecamp,frq,1,dz))<0) // Get amplitude on spectral envelope of new-spectrum, at this freq
  7903. return(exit_status);
  7904. if((exit_status = getspecenvamp(&origspecamp,frq,0,dz))<0) // Get amplitude on spectral envelope of original-spectrum, at this freq
  7905. return(exit_status);
  7906. if(newspecamp <= 0.0) // Check for zeros, in either spectrum
  7907. dz->windowbuf[0][AMPP] = 0.0f;
  7908. else {
  7909. vocode_ratio = origspecamp/newspecamp;
  7910. thisamp = dz->windowbuf[0][AMPP] * vocode_ratio;
  7911. if(thisamp < VERY_TINY_VAL)
  7912. dz->windowbuf[0][AMPP] = 0.0f;
  7913. else
  7914. dz->windowbuf[0][AMPP] = (float)thisamp;
  7915. }
  7916. }
  7917. if(tail > 0) { // Any top-of-spectrum insertions, tail away to zero
  7918. for(k = 1,cc = dz->clength-1,vc = cc*2;k <= tail;k++,cc--,vc-=2) {
  7919. incr = pow((double)k/(double)(tail+1),TAILOFF_SLOPE);
  7920. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * incr);
  7921. }
  7922. }
  7923. }
  7924. // Finally, copy transformed spectrum back into flbufptr, ready for output
  7925. memcpy((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],dz->wanted * sizeof(float));
  7926. }
  7927. }
  7928. // Now advance phase of arpeggiator
  7929. *up = nextup;
  7930. *phase = nextphase;
  7931. // Do any spoecified lopass and hipass filtering
  7932. if(dz->param[COL_LO] > 0.0) {
  7933. searchfrqlimit = dz->param[COL_LO] + (dz->chwidth * 2);
  7934. for(cc=0,vc=0;cc <dz->clength;cc++,vc+=2) {
  7935. if(dz->flbufptr[0][FREQ] < dz->param[COL_LO])
  7936. dz->flbufptr[0][AMPP] = 0.0f;
  7937. else if(dz->flbufptr[0][FREQ] > searchfrqlimit)
  7938. break;
  7939. }
  7940. }
  7941. if(dz->param[COL_HI] > 0.0) {
  7942. searchfrqlimit = dz->param[COL_HI] - (dz->chwidth * 2);
  7943. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7944. if(dz->flbufptr[0][FREQ] < searchfrqlimit)
  7945. continue;
  7946. else if(dz->flbufptr[0][FREQ] > dz->param[COL_HI])
  7947. dz->flbufptr[0][AMPP] = 0.0f;
  7948. }
  7949. }
  7950. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  7951. return(exit_status);
  7952. if(post_amptotal > pre_amptotal) {
  7953. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  7954. return(exit_status);
  7955. }
  7956. // Apply any user entered attenuation
  7957. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  7958. for(vc=0;vc<dz->wanted;vc+=2)
  7959. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  7960. }
  7961. return FINISHED;
  7962. }
  7963. /************************* ARPEGGIATE *************************
  7964. *
  7965. * Arpeggaite runs a small, inverted cosin, window over the first 16 harmonics,
  7966. * recycling baclk to harmonic 1, qwhen it overruns the top of this range.
  7967. *
  7968. * So, if the input phase is in range 0 to 1, the position within this ARPEG_RANGE window is in range 0 to 7 (inclusive)
  7969. *
  7970. * The window itself is ARPEG_WIN_WIDTH partials wide. | 1 |
  7971. * | _ |
  7972. * So, any partial (i.e. data in dz->windowbuf[0]) falling under this window | / \ |
  7973. * (OR any data at all, in the flbufptr, when non-harmonic data not Suppressed). | / \ -->>|
  7974. * has its amplitude multiplied by the window. | 0 / \ 0 |
  7975. * | _ / \ _ |
  7976. * | _ |
  7977. * Partial Nos 0 1 2 3 4 5 6 7
  7978. * Root multipliers 1 2 3 4 5 6 7 8
  7979. */
  7980. int arpeggiate(double *arpegamp,float frq,double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int is_split,dataptr dz)
  7981. {
  7982. double frq_offset_under_window, shaping;
  7983. if(frq > lobandbot && frq < lobandtop) {
  7984. frq_offset_under_window = (frq - lobandbot)/bwidth;
  7985. shaping = -cos(frq_offset_under_window * TWOPI); // Range -1/+1/-1
  7986. shaping = max(0.0,shaping + 1.0); // Range 0 /+2/ 0
  7987. shaping = min(1.0,shaping/2.0); // Range 0 /+1/ 0
  7988. } else if(is_split && (frq > hibandbot && frq < hibandtop)) {
  7989. frq_offset_under_window = (frq - hibandbot)/bwidth;
  7990. shaping = -cos(frq_offset_under_window * TWOPI); // Range -1/+1/-1
  7991. shaping = max(0.0,shaping + 1.0); // Range 0 /+2/ 0
  7992. shaping = min(1.0,shaping/2.0); // Range 0 /+1/ 0
  7993. } else
  7994. shaping = 0.0; // Zero partial amplitude
  7995. *arpegamp = shaping;
  7996. return FINISHED;
  7997. }
  7998. /************************************ FIND_AND_CHANGE_PARTIALS ***************************/
  7999. int find_and_change_partials(float the_fundamental,float newfrq,int *isharm,double frqshift,double frqtrans,double randomisation,
  8000. double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int do_arpegg,int is_split,dataptr dz)
  8001. {
  8002. int exit_status, cc, vc, thiscc, kcc, kvc, newcc, harmonic_found_in_src, harmonic_no;
  8003. int most_appropriate_chan, harmonicbandcnt, firstchan_with_harmonic, lastchan_with_harmonic, above_most_approp_offset, below_most_approp_offset;
  8004. float thisfrq, chancentre, thatchancentre, thatfrq, the_harmonicfrq;
  8005. double this_chan_frq_offset, that_chan_frq_offset, specamp = 0.0, arpegamp;
  8006. double rand;
  8007. the_harmonicfrq = the_fundamental;
  8008. harmonic_no = 1;
  8009. harmonic_found_in_src = 0;
  8010. // HARMONICS FOUND IN SRC IN MULTIPLE CHANNELS, Have multiple channels in output
  8011. // If a particular harmonic NOT FOUND in src, put it in a single channel in output
  8012. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  8013. thisfrq = dz->flbufptr[0][FREQ];
  8014. if(is_above_equivalent_pitch(thisfrq,the_harmonicfrq,dz)) { // Once the channel data is higher than the current harmonic frq, move to next harmonic
  8015. if(!harmonic_found_in_src) {
  8016. if(newfrq < dz->nyquist && newfrq > FSPEC_MINFRQ) { // BUT if no channel with current harmonic HAS BEEN found, insert it in a single channel
  8017. if(do_arpegg) {
  8018. if((exit_status = arpeggiate(&arpegamp,the_harmonicfrq,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,is_split,dz))<0)
  8019. return exit_status;
  8020. } else
  8021. arpegamp = 1.0;
  8022. thiscc = (int)floor((fabs(newfrq) + dz->halfchwidth)/dz->chwidth);
  8023. vc = thiscc*2;
  8024. dz->windowbuf[0][FREQ] = newfrq;
  8025. if((exit_status = getspecenvamp(&specamp,newfrq,0,dz))<0)
  8026. return(exit_status);
  8027. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);
  8028. }
  8029. }
  8030. the_harmonicfrq += the_fundamental; // Move to next harmonic
  8031. harmonic_no++;
  8032. if(the_harmonicfrq >= dz->nyquist)
  8033. break;
  8034. harmonic_found_in_src = 0; // Set flag telling us whether THIS harmonic is founds in src
  8035. if(dz->mode == F_RAND) {
  8036. rand = (drand48() * 2.0) - 1.0; // For rand option, generate number in range -1 TO +1 or less
  8037. rand /= 2.0; // to range +- 1/2.
  8038. rand *= randomisation; // Some value with this range, or a smaller range around centre at 0.0
  8039. frqshift = the_fundamental * rand; // Step is <= +- 1/2 distance between harmonics
  8040. }
  8041. switch(dz->mode) { // Do the frq change required
  8042. case(F_RESPACE): newfrq = (float)(the_fundamental + (frqshift * harmonic_no)); break;
  8043. case(F_OCTSHIFT): // fall thro
  8044. case(F_PINVERT): // fall thro
  8045. case(F_PEXAGG): // fall thro
  8046. case(F_PQUANT): // fall thro
  8047. case(F_PCHRAND): // fall thro
  8048. case(F_TRANS): newfrq = (float)(the_harmonicfrq * frqtrans); break;
  8049. case(F_FRQSHIFT): // fall thro
  8050. case(F_RAND): newfrq = (float)min(FSPEC_MINFRQ,max((float)(the_harmonicfrq + frqshift),dz->nyquist)); break;
  8051. case(F_ARPEG): newfrq = the_harmonicfrq; break;
  8052. }
  8053. if(newfrq >= dz->nyquist || newfrq < FSPEC_MINFRQ) // If shifted frq becomes out of range, quit
  8054. break;
  8055. }
  8056. if(is_equivalent_pitch(thisfrq,the_harmonicfrq,dz)) { // IF freq in channel a harmonic
  8057. if(do_arpegg) {
  8058. if((exit_status = arpeggiate(&arpegamp,the_harmonicfrq,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,is_split,dz))<0)
  8059. return exit_status;
  8060. } else
  8061. arpegamp = 1.0;
  8062. isharm[cc] = 1;
  8063. harmonic_found_in_src = 1;
  8064. chancentre = (float)(cc * dz->chwidth); // Look in channels immediately above this
  8065. this_chan_frq_offset = fabs(thisfrq - chancentre);
  8066. most_appropriate_chan = cc;
  8067. harmonicbandcnt = 1;
  8068. firstchan_with_harmonic = cc;
  8069. lastchan_with_harmonic = cc;
  8070. kcc = cc + 1; // How many adjacent channels contain this harmonic
  8071. for(kvc = kcc*2;kcc < dz->clength;kcc++,kvc+=2) {
  8072. thatchancentre = (float)(kcc * dz->chwidth); // And which channel-centre is closest to the harmonic-frq
  8073. thatfrq = dz->flbufptr[0][kvc+1];
  8074. if(is_equivalent_pitch(thatfrq,the_harmonicfrq,dz)) {
  8075. isharm[kcc] = 1;
  8076. harmonicbandcnt++;
  8077. that_chan_frq_offset = fabs(thatfrq - thatchancentre);
  8078. if(that_chan_frq_offset < this_chan_frq_offset) {
  8079. most_appropriate_chan = kcc;
  8080. this_chan_frq_offset = that_chan_frq_offset;
  8081. }
  8082. }
  8083. else // If no futher adjacent channels containing this harmonic are found
  8084. break; // break from search for further chans containing the harmonic.
  8085. }
  8086. // Put the transposed harmonic into the appropriate new channel
  8087. newcc = (int)floor((fabs(newfrq) + dz->halfchwidth)/dz->chwidth);
  8088. vc = newcc*2;
  8089. dz->windowbuf[0][FREQ] = newfrq; // windowbuf stores the transposed-harmonics data
  8090. if((exit_status = getspecenvamp(&specamp,newfrq,0,dz))<0) // but under the original formant envelope
  8091. return(exit_status);
  8092. if(harmonicbandcnt > 1) // If harmonic appeared in > 1 adjacent channels
  8093. specamp /= (double)harmonicbandcnt; // Divide amp between chans that share this frequency
  8094. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);
  8095. if(harmonicbandcnt > 1) { // If harmonic appeared in > 1 adjacent channels
  8096. lastchan_with_harmonic = kcc-1;
  8097. above_most_approp_offset = lastchan_with_harmonic - most_appropriate_chan;
  8098. below_most_approp_offset = most_appropriate_chan - firstchan_with_harmonic;
  8099. if(below_most_approp_offset > 0) { // Fill same number of adjacent channels at new location
  8100. thiscc = max(newcc - below_most_approp_offset,0);
  8101. for(vc = thiscc*2;thiscc < newcc;thiscc++,vc+=2) {
  8102. dz->windowbuf[0][FREQ] = newfrq;
  8103. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);;
  8104. }
  8105. }
  8106. if(above_most_approp_offset > 0) {
  8107. thiscc = min(newcc + above_most_approp_offset,dz->clength - 1);
  8108. for(vc = thiscc*2;thiscc > newcc;thiscc--,vc-=2) {
  8109. dz->windowbuf[0][FREQ] = newfrq;
  8110. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);
  8111. }
  8112. }
  8113. }
  8114. cc = lastchan_with_harmonic; // Move search to last appearance of this harmonic
  8115. vc = cc * 2;
  8116. the_harmonicfrq += the_fundamental; // And go to next harmonic
  8117. harmonic_no++;
  8118. if(the_harmonicfrq >= dz->nyquist)
  8119. break;
  8120. if(dz->mode ==F_RAND) { // Generating the next transformed frq
  8121. rand = (drand48() * 2.0) - 1.0;
  8122. rand /= 2.0;
  8123. rand *= randomisation;
  8124. frqshift = the_fundamental * rand;
  8125. }
  8126. switch(dz->mode) {
  8127. case(F_RESPACE): newfrq = (float)(the_fundamental + (frqshift * harmonic_no)); break;
  8128. case(F_OCTSHIFT): // fall thro
  8129. case(F_PINVERT): // fall thro
  8130. case(F_PEXAGG): // fall thro
  8131. case(F_PQUANT): // fall thro
  8132. case(F_PCHRAND): // fall thro
  8133. case(F_TRANS): newfrq = (float)(the_harmonicfrq * frqtrans); break;
  8134. case(F_FRQSHIFT): // fall thro
  8135. case(F_RAND): newfrq = (float)(the_harmonicfrq + frqshift); break;
  8136. case(F_ARPEG): newfrq = the_harmonicfrq; break;
  8137. }
  8138. if(newfrq >= dz->nyquist || newfrq < FSPEC_MINFRQ) // If shifted frq becomes out of range, quit
  8139. break;
  8140. }
  8141. }
  8142. return FINISHED;
  8143. }
  8144. /************************************ IS_COLORING ***************************/
  8145. int is_coloring(dataptr dz)
  8146. {
  8147. switch(dz->mode) {
  8148. case(F_OCTSHIFT): // fall thro
  8149. case(F_TRANS): // fall thro
  8150. case(F_FRQSHIFT): // fall thro
  8151. case(F_RESPACE): // fall thro
  8152. case(F_PINVERT): // fall thro
  8153. case(F_PEXAGG): // fall thro
  8154. case(F_PQUANT): // fall thro
  8155. case(F_PCHRAND): // fall thro
  8156. case(F_RAND): return TRUE; break;
  8157. }
  8158. return FALSE;
  8159. }
  8160. /************************************ DO_TOP_OF_SPECTRUM_FILL ***************************/
  8161. int do_top_of_spectrum_fill(int cc,float endamp,float the_fundamental,double frqtrans,double frqshift,int *tail,dataptr dz)
  8162. {
  8163. int finished = 0, newcc, lastnewcc = -1;
  8164. float newfrq;
  8165. double frq;
  8166. frq = dz->nyquist;
  8167. while (!finished) {
  8168. frq += dz->chwidth;
  8169. switch(dz->mode) {
  8170. case(F_OCTSHIFT): // fall thro
  8171. case(F_TRANS): // fall thro
  8172. case(F_FRQSHIFT):
  8173. if(dz->mode == F_FRQSHIFT)
  8174. newfrq = (float)(frq + frqshift);
  8175. else
  8176. newfrq = (float)(frq * frqtrans);
  8177. newcc = (int)round(newfrq/dz->chwidth);
  8178. if(newcc >= 0 && newcc <= dz->clength-1) {
  8179. dz->windowbuf[0][newcc*2 + 1] = newfrq;
  8180. dz->windowbuf[0][newcc*2] = endamp;
  8181. if(newcc > lastnewcc)
  8182. (*tail)++;
  8183. lastnewcc = newcc;
  8184. } else
  8185. finished = 1;
  8186. break;
  8187. case(F_RESPACE):
  8188. newfrq = (float)frq;
  8189. if(newfrq >= the_fundamental) {
  8190. newfrq -= the_fundamental;
  8191. newfrq *= (float)(frqshift/the_fundamental);
  8192. newfrq += the_fundamental;
  8193. }
  8194. newcc = (int)round(newfrq/dz->chwidth);
  8195. if(newcc >= 0 && newcc <= dz->clength-1) {
  8196. dz->windowbuf[0][newcc*2 + 1] = (float)(newfrq);
  8197. dz->windowbuf[0][newcc*2] = endamp;
  8198. if(newcc > lastnewcc)
  8199. (*tail)++;
  8200. lastnewcc = newcc;
  8201. } else
  8202. finished = 1;
  8203. break;
  8204. }
  8205. }
  8206. return FINISHED;
  8207. }
  8208. /************************************ GETMEANPITCH ***************************/
  8209. int getmeanpitch(double *meanpitch,double *minpitch,double *maxpitch,dataptr dz)
  8210. {
  8211. int n, sumcnt = 0;
  8212. double maxpitchfrq = -HUGE, minpitchfrq = HUGE;
  8213. *meanpitch = 0.0;
  8214. for(n = 0; n < dz->wlength; n++) {
  8215. if(dz->pitches[n] >= MINPITCH) {
  8216. maxpitchfrq = max(maxpitchfrq,dz->pitches[n]);
  8217. minpitchfrq = min(minpitchfrq,dz->pitches[n]);
  8218. *meanpitch += unchecked_hztomidi(dz->pitches[n]);
  8219. sumcnt++;
  8220. }
  8221. }
  8222. *meanpitch /= (double)sumcnt;
  8223. *minpitch = unchecked_hztomidi(minpitchfrq);
  8224. *maxpitch = unchecked_hztomidi(maxpitchfrq);
  8225. if(*maxpitch < 0.0) {
  8226. sprintf(errstr,"Failed to find maximum pitch in pitch data: (Possibly no definite pitch in file??)\n");
  8227. return GOAL_FAILED;
  8228. }
  8229. if(*minpitch > 200) {
  8230. sprintf(errstr,"Failed to find minimum pitch in pitch data: (Possibly no definite pitch in file??)\n");
  8231. return GOAL_FAILED;
  8232. }
  8233. return FINISHED;
  8234. }
  8235. /************************** INTERVAL_MAPPING ************************
  8236. *
  8237. * Approximate input interval to nearest value in LHS column of input map.
  8238. * Find variance from that value.
  8239. * Return corresponding value in RHS column of map, with the variance correction added.
  8240. */
  8241. int interval_mapping(double *thisint,double thismidi,dataptr dz)
  8242. {
  8243. double *p = dz->parray[F_PINTMAP], *q;
  8244. double *pend = dz->parray[F_PINTMAP] + (dz->itemcnt * 2);
  8245. double variance, v1, v2;
  8246. // Normally, points to the normal upeard interval
  8247. q = p+1; // and q points to the correspoinding downward interval
  8248. if(*p < 0.0) { // But interval is already downward (-ve)
  8249. p = q; // we read the inverted intervals column
  8250. q = p-1; // and map to the non-inverted
  8251. }
  8252. if(thismidi <= *p) { /* intvl is below all entries in mapping table */
  8253. variance = thismidi - *p;
  8254. *thisint = *q - variance; /* return map of bottom val (-variance) */
  8255. return(FINISHED);
  8256. }
  8257. while(thismidi > *p) {
  8258. p += 2;
  8259. q += 2;
  8260. if(p >= pend) { /* intvl is above all entries in mapping table */
  8261. p -= 2;
  8262. q -= 2;
  8263. variance = thismidi - *p;
  8264. *thisint = *q - variance; /* return map of top val (-variance) */
  8265. return(FINISHED);
  8266. }
  8267. }
  8268. v1 = *p - thismidi; /* intvl is between 2 entries in mapping table */
  8269. v2 = thismidi - *(p-2);
  8270. if(v1 > v2) { /* Compare variances, to find which intvl closer */
  8271. variance = v2;
  8272. *thisint = *(q-2) - variance;
  8273. } else {
  8274. variance = v1;
  8275. *thisint = *q + variance; /* return appropriate mapped pitch (+/-variance) */
  8276. }
  8277. return(FINISHED);
  8278. }
  8279. /********************** READ_INTERVAL_MAPPING ************************/
  8280. int read_interval_mapping(char *filename,dataptr dz)
  8281. {
  8282. int exit_status;
  8283. double *p;
  8284. int n, m;
  8285. double src_n, src_m, goal_n, goal_m;
  8286. if(!strcmp(filename,"0"))
  8287. dz->is_mapping = FALSE;
  8288. else {
  8289. // Get data from textfile
  8290. if((exit_status = get_and_count_data_from_textfile(filename,&(dz->parray[F_PINTMAP]),dz))<0)
  8291. return(exit_status);
  8292. p = dz->parray[F_PINTMAP];
  8293. // Check range of data
  8294. for(n=0;n<dz->itemcnt;n++) {
  8295. if(*p < -MAXINTRANGE || *p > MAXINTRANGE) {
  8296. sprintf(errstr,
  8297. "Mapping val (%lf) out of range (%.0lf to -%.0lf semitones) (8 8vas up or down).\n",
  8298. *p,MAXINTRANGE,MAXINTRANGE);
  8299. return(DATA_ERROR);
  8300. }
  8301. p++;
  8302. }
  8303. if(ODD(dz->itemcnt)) {
  8304. sprintf(errstr,"Data not paired correctly in mapping file\n");
  8305. return(DATA_ERROR);
  8306. }
  8307. // Sort mapping data
  8308. for(n=0;n<dz->itemcnt-2;n+=2) {
  8309. src_n = dz->parray[F_PINTMAP][n];
  8310. goal_n = dz->parray[F_PINTMAP][n+1];
  8311. for(m = n+2;m<dz->itemcnt;m+=2) {
  8312. src_m = dz->parray[F_PINTMAP][m];
  8313. goal_m = dz->parray[F_PINTMAP][m+1];
  8314. if(src_n > src_m) {
  8315. dz->parray[F_PINTMAP][n] = src_m;
  8316. dz->parray[F_PINTMAP][m] = src_n;
  8317. dz->parray[F_PINTMAP][n+1] = goal_m;
  8318. dz->parray[F_PINTMAP][m+1] = goal_n;
  8319. src_n = src_m;
  8320. goal_n = goal_m;
  8321. }
  8322. }
  8323. }
  8324. dz->itemcnt /= 2;
  8325. dz->is_mapping = TRUE;
  8326. }
  8327. return(FINISHED);
  8328. }
  8329. /*************************** GET_AND_COUNT_DATA_FROM_TEXTFILE ******************************
  8330. *
  8331. * (1) Gets double table data from a text file.
  8332. * (2) counts ALL items (not pairing them).
  8333. * (3) Does NOT check for in-range.
  8334. */
  8335. int get_and_count_data_from_textfile(char *filename,double **brktable,dataptr dz)
  8336. {
  8337. FILE *fp;
  8338. double *p, dummy;
  8339. char temp[200], *q;
  8340. int n = 0;
  8341. if((fp = fopen(filename,"r"))==NULL) {
  8342. sprintf(errstr, "Can't open textfile %s to read data.\n",filename);
  8343. return(DATA_ERROR);
  8344. }
  8345. n = 0;
  8346. while(fgets(temp,200,fp)==temp) {
  8347. q = temp;
  8348. if(*q == ';') // Allow comments in file
  8349. continue;
  8350. while(get_float_from_within_string(&q,&dummy))
  8351. n++;
  8352. }
  8353. if(n == 0) {
  8354. sprintf(errstr,"No data in special data file %s\n",filename);
  8355. return(DATA_ERROR);
  8356. }
  8357. if((*brktable = (double *)malloc(n * sizeof(double)))==NULL) {
  8358. sprintf(errstr,"INSUFFICIENT MEMORY for data.\n");
  8359. return(MEMORY_ERROR);
  8360. }
  8361. p = *brktable;
  8362. rewind(fp);
  8363. while(fgets(temp,200,fp)==temp) {
  8364. q = temp;
  8365. if(*q == ';') // Allow comments in file
  8366. continue;
  8367. while(get_float_from_within_string(&q,p))
  8368. p++;
  8369. }
  8370. if(fclose(fp)<0) {
  8371. fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
  8372. fflush(stdout);
  8373. }
  8374. dz->itemcnt = n;
  8375. return(FINISHED);
  8376. }
  8377. /************************************* EXAG_PITCHLINE ******************************/
  8378. int exag_pitchline(float *newfrq,float thisfrq,double minpich,double maxpich,dataptr dz)
  8379. {
  8380. int exit_status;
  8381. double meanpich, thisint, thispich;
  8382. dz->time = 0.0f;
  8383. meanpich = dz->param[COLFLT];
  8384. if((exit_status = hztomidi(&thispich,thisfrq))<0)
  8385. return(exit_status);
  8386. if(maxpich - meanpich > SEMITONES_PER_OCTAVE);
  8387. maxpich = meanpich + SEMITONES_PER_OCTAVE;
  8388. if(meanpich - minpich > SEMITONES_PER_OCTAVE);
  8389. minpich = meanpich - SEMITONES_PER_OCTAVE;
  8390. /* if contour variable specified */
  8391. if(dz->vflag[EXAG_HITIE]) { // TIES TO TOP OF RANGE
  8392. if(thispich > meanpich)
  8393. thispich = (float)maxpich;
  8394. else if(dz->vflag[EXAG_MIDTIE] && !dz->vflag[EXAG_LOTIE])
  8395. thispich = (float)meanpich;
  8396. }
  8397. if(dz->vflag[EXAG_LOTIE]) {
  8398. if(thispich < meanpich)
  8399. thispich = (float)minpich;
  8400. else if(dz->vflag[EXAG_MIDTIE] && !dz->vflag[EXAG_HITIE])
  8401. thispich = (float)meanpich;
  8402. }
  8403. /* If range variable specified */
  8404. if(dz->param[EXAGRANG] > 0.0) { // -1 flags no range variation
  8405. if(thispich>=meanpich) {
  8406. if(!dz->vflag[ONLY_BELOW]) {
  8407. thisint = thispich - meanpich; // What is interval from mean to this pitch
  8408. thispich = meanpich + (thisint * dz->param[EXAGRANG]);
  8409. }
  8410. } else { // Exaggerate it
  8411. if(!dz->vflag[ONLY_ABOVE]) {
  8412. thisint = meanpich - thispich; // and add-to/subtract-from mean
  8413. thispich = meanpich - (thisint * dz->param[EXAGRANG]);
  8414. }
  8415. }
  8416. } // Force pitch to be within range
  8417. thispich = min(dz->param[COLHIPCH],max(dz->param[COLLOPCH],thispich));
  8418. *newfrq = (float)miditohz(thispich);
  8419. return(FINISHED);
  8420. }
  8421. /************************************* PITCH_INVERT ******************************/
  8422. int pitch_invert(float *newfrq,float the_fundamental,dataptr dz)
  8423. {
  8424. int exit_status;
  8425. double pivotpitch, rootpitch, newpitch, thisintvl, newintvl;
  8426. pivotpitch = dz->param[COLINT];
  8427. rootpitch = unchecked_hztomidi(the_fundamental);
  8428. thisintvl = pivotpitch - rootpitch;
  8429. if(dz->is_mapping) {
  8430. if((exit_status = interval_mapping(&newintvl,thisintvl,dz))<0)
  8431. return(exit_status);
  8432. thisintvl = newintvl;
  8433. }
  8434. newpitch = max(dz->param[COLLOPCH],min(dz->param[COLHIPCH],pivotpitch + thisintvl));
  8435. *newfrq = (float)miditohz(newpitch);
  8436. return FINISHED;
  8437. }
  8438. /********************************** PITCH_QUANTISE_ALL **************************/
  8439. int pitch_quantise_all(dataptr dz)
  8440. {
  8441. int exit_status, at_timehfend = 0;
  8442. double *pstt, *pend, *abs_pend = NULL, *next_pstt = NULL, *next_pend = NULL;
  8443. double thismidi, qmidi, qmidi1, qmidi2, thistime = 0.0, nexttime = 0.0, time, time_ratio = 1.0;
  8444. int n;
  8445. pstt = dz->parray[QUANTPITCH];
  8446. if(dz->timedhf) {
  8447. abs_pend = pstt + (dz->quantcnt * dz->itemcnt) - 1;
  8448. thistime = 0.0;
  8449. pend = pstt + dz->quantcnt - 1;
  8450. if(pend >= abs_pend)
  8451. at_timehfend = 1;
  8452. else {
  8453. next_pstt = pstt + dz->quantcnt;
  8454. next_pend = next_pstt + dz->quantcnt - 1;
  8455. nexttime = *next_pstt;
  8456. }
  8457. } else
  8458. pend = pstt + dz->quantcnt - 1;
  8459. for(n=0;n<dz->wlength;n++) {
  8460. if(dz->pitches[n] < MINPITCH) {
  8461. dz->pitches2[n] = dz->pitches[n];
  8462. continue;
  8463. }
  8464. if(dz->timedhf && !at_timehfend){
  8465. time = dz->frametime * n;
  8466. if(time > nexttime) {
  8467. if(next_pstt + dz->quantcnt >= abs_pend) {
  8468. at_timehfend = 1;
  8469. pstt++; // Change to the normal convention, MIDI data starts AFTER the time value
  8470. } else {
  8471. thistime = nexttime;
  8472. pstt = next_pstt;
  8473. pend = next_pend;
  8474. next_pstt += dz->quantcnt;
  8475. next_pend += dz->quantcnt;
  8476. nexttime = *next_pstt;
  8477. }
  8478. }
  8479. if(!at_timehfend)
  8480. time_ratio = (time - thistime)/(nexttime - thistime);
  8481. }
  8482. if((exit_status = hztomidi(&thismidi,dz->pitches[n]))<0)
  8483. return(exit_status);
  8484. if(dz->timedhf && !at_timehfend) {
  8485. qmidi1 = pitch_quantise(thismidi,pstt+1,pend,dz); // pstt is a time val: Timevarying HF MIDI vals start at pstt+1
  8486. qmidi2 = pitch_quantise(thismidi,next_pstt+1,next_pend,dz);
  8487. qmidi = ((qmidi2 - qmidi1) * time_ratio) + qmidi1;
  8488. } else
  8489. qmidi = pitch_quantise(thismidi,pstt,pend,dz);
  8490. dz->pitches2[n] = (float)miditohz(qmidi);
  8491. }
  8492. // NOW SMOOTH THE DATA
  8493. return pitch_smooth(dz);
  8494. }
  8495. /********************************** PITCH_QUANTISE **************************/
  8496. double pitch_quantise(double thismidi,double *pstt, double *pend,dataptr dz)
  8497. {
  8498. double *p, qmidi;
  8499. if(thismidi <= *pstt)
  8500. qmidi = *pstt;
  8501. else if(thismidi >= *pend)
  8502. qmidi = *pend;
  8503. else {
  8504. p = pstt;
  8505. while(thismidi > *p)
  8506. p++;
  8507. if((*p - thismidi) > (thismidi - *(p-1)))
  8508. qmidi = *(p-1);
  8509. else
  8510. qmidi = *p;
  8511. }
  8512. return qmidi;
  8513. }
  8514. /********************************** PITCH_SMOOTH **************************/
  8515. int pitch_smooth(dataptr dz)
  8516. {
  8517. int exit_status, min_wcnt;
  8518. float previouspitch;
  8519. previouspitch = -1;
  8520. if(dz->vflag[Q_ORNAMENTS])
  8521. min_wcnt = (int)round(ORNAMENT_DUR/dz->frametime);
  8522. else
  8523. min_wcnt = (int)round(STABLE_DUR/dz->frametime);
  8524. // Pass 1: remove too-brief pitches
  8525. if((exit_status = pitchline_smooth(dz->pitches2,min_wcnt,0,dz))<0)
  8526. return exit_status;
  8527. if(dz->vflag[Q_NOSMOOTH])
  8528. return FINISHED;
  8529. // Pass 2: put in note-transitions
  8530. return smooth_note_to_note_transitions(dz->pitches2,dz);
  8531. }
  8532. /********************************** PITCH_RANDOMISE_ALL **************************
  8533. *
  8534. * Randomisation takes place over time-slots, themselves generated at randon.
  8535. * Time slots are based on a minimum time-slot, and range up to a max of PRAND_TRANGE * the min.
  8536. * To ensure we do not get a bias towards the longer slots, we take the sqrt of any value we get gtom drand48()
  8537. *
  8538. * tslot = (int)round(sqrt(drand48()) * PRAND_TRANGE) * min_wcnt);
  8539. */
  8540. int pitch_randomise_all(dataptr dz)
  8541. {
  8542. int exit_status, min_wcnt, tslot, blokcnt;
  8543. double *pstt, *pend, prand_range;
  8544. float thispitch, nextpitch;
  8545. int n, m, newwcnt;
  8546. if(dz->vflag[Q_ORNAMENTS])
  8547. min_wcnt = (int)floor(PRAND_ORN_TSTEP/dz->frametime);
  8548. else
  8549. min_wcnt = (int)floor(PRAND_TSTEP/dz->frametime);
  8550. if(dz->quantcnt) {
  8551. pstt = dz->parray[QUANTPITCH];
  8552. pend = dz->parray[QUANTPITCH] + dz->quantcnt - 1;
  8553. blokcnt = 0;
  8554. for(n=0;n<dz->wlength;n++) { // For all previously quantised pitches
  8555. thispitch = dz->pitches2[n]; // Get the startpitch of a blok having a fixed-quantised pitch
  8556. m = n;
  8557. do {
  8558. blokcnt++;
  8559. if(++m >= dz->wlength)
  8560. break;
  8561. nextpitch = dz->pitches2[m]; // count the bloksize
  8562. } while(nextpitch == thispitch);
  8563. if(blokcnt > min_wcnt) { // If the block of pitch is longer than the minimum bloksize
  8564. newwcnt = 0;
  8565. while(newwcnt < blokcnt) { // Generate rand time-slots within the blok
  8566. prand_range = (double)(blokcnt - newwcnt)/(double)min_wcnt; // Set range for random-generation between min and remaining bloksize
  8567. tslot = ((int)round(sqrt(drand48()) * prand_range) * min_wcnt) + min_wcnt;
  8568. if(newwcnt + tslot > blokcnt - min_wcnt) // If the time-slot does not leave enough space for a a futher slot, within the blok
  8569. tslot = blokcnt - newwcnt; // Forece the time-slot to take up all the remainder of the blok
  8570. // Random-generate a new pitch, and quantise it to the quantisation grid
  8571. if((exit_status = quantise_randomise_pitchblok(n,tslot,pstt,pend,dz))<0)
  8572. return exit_status;
  8573. // Set the range for random-generation between min and this bloksize
  8574. newwcnt += tslot; // Keep a running sum of window used within the pitchblok
  8575. }
  8576. } else if((exit_status = quantise_randomise_pitchblok(n,blokcnt,pstt,pend,dz))<0)
  8577. return exit_status;
  8578. blokcnt = 0;
  8579. n = m - 1; // Advance the outer loop to where inner loop has got to
  8580. }
  8581. } else {
  8582. newwcnt = 0; // For all pitches
  8583. for(n=0;n<dz->wlength;n++) {
  8584. if((exit_status = randomise_pitchblok(n,min_wcnt,&newwcnt,dz))<0)
  8585. return exit_status; // Rand-transposes a block of data in a random-sized timeslot
  8586. n = newwcnt - 1; // Outer loop jumps over transformed windows
  8587. }
  8588. }
  8589. return FINISHED;
  8590. }
  8591. /********************************** RANDOMISE_PITCHBLOK **************************/
  8592. int randomise_pitchblok(int start_win,int min_wcnt,int *newwcnt,dataptr dz)
  8593. {
  8594. int exit_status, tslot;
  8595. double thisintv;
  8596. int k, m;
  8597. tslot = ((int)round(sqrt(drand48()) * PRAND_TRANGE) * min_wcnt) + min_wcnt;
  8598. if(*newwcnt + tslot > dz->wlength - min_wcnt) // If it reaches too close to the end of the pitch data
  8599. tslot = dz->wlength - *newwcnt; // extend slot to end of pitch data.
  8600. if((exit_status = get_rand_interval(&thisintv,dz)) < 0)
  8601. return exit_status; // Add a random interval to all pitches in this slot
  8602. for(k = 0,m = start_win; k < tslot;k++,m++)
  8603. dz->pitches2[m] = (float)(dz->pitches[m] + thisintv);
  8604. *newwcnt += tslot; // Advance the cnt of transformed windows
  8605. return FINISHED;
  8606. }
  8607. /********************************** QUANTISE_RANDOMISE_PITCHBLOK **************************/
  8608. int quantise_randomise_pitchblok(int n,int wcnt,double *pstt,double *pend,dataptr dz)
  8609. {
  8610. int exit_status;
  8611. double thisintv, thispitch;
  8612. int k;
  8613. if((exit_status = get_rand_interval(&thisintv,dz)) < 0) // Generate random interval
  8614. return exit_status;
  8615. thispitch = dz->pitches2[n]; // Add interval to current pitchblok pitch
  8616. thispitch += thisintv;
  8617. thispitch = pitch_quantise(thispitch,pstt,pend,dz); // Quantise the resulting pitch
  8618. for(k=0;k <wcnt;k++) // Refill the pitchblock with the new pitch
  8619. dz->pitches2[n++] = (float)thispitch;
  8620. return FINISHED;
  8621. }
  8622. /************************** GET_RAND_INTERVAL ************************/
  8623. int get_rand_interval(double *thisintv,dataptr dz)
  8624. {
  8625. double wiggle2, wiggle = (((drand48()) * 2.0) - 1.0); // Range -1 to 1; Then fabsRange 0 - 1 warped, biasing values to top
  8626. wiggle2 = pow(fabs(wiggle),0.33); // - -
  8627. if(wiggle < 0.0) // - -
  8628. wiggle = -wiggle2; // - ->> -
  8629. else // - -
  8630. wiggle = wiggle2; // - -
  8631. // - -
  8632. *thisintv = dz->param[FPRMAXINT] * wiggle;
  8633. if(wiggle > 0.0) { // If varies upwards
  8634. if(dz->param[FSLEW] < 1.0) // If slew is (say) 0.5, upper range is 1/2 of lower range, so multiply by slew
  8635. *thisintv *= dz->param[FSLEW];
  8636. } else if(wiggle < 0.0) { // If varies downwards
  8637. if(dz->param[FSLEW] > 1.0) // If slew is (say) 2, lower range is 1/2 of upper range, so divide by slew
  8638. *thisintv /= dz->param[FSLEW];
  8639. }
  8640. return(FINISHED);
  8641. }
  8642. /************************** FORMANTS_SMOOTH_AND_QUANTISE_ALL ************************/
  8643. int formants_smooth_and_quantise_all(dataptr dz)
  8644. {
  8645. int exit_status, fno, offset, qdep_param, min_wcnt, at_timehfend = 0;
  8646. int n;
  8647. double thismidi, qmidi, qmidi1, qmidi2, quantintvl, time, thistime = 0, nexttime = 0.0, time_ratio = 1.0;
  8648. double *pstt = NULL, *pend = NULL, *next_pstt = NULL, *next_pend = NULL, *abs_pend = NULL;
  8649. float *ffrq[5], *qfrq[5];
  8650. min_wcnt = (int)floor(PRAND_TSTEP/dz->frametime); // Min number of windows to indicate a stable pitch
  8651. ffrq[1] = dz->fptr[FOR_FRQ1];
  8652. ffrq[2] = dz->fptr[FOR_FRQ2]; // Point to appropriate arrays storing formant frq-data
  8653. ffrq[3] = dz->fptr[FOR_FRQ3];
  8654. ffrq[4] = dz->fptr[FOR_FRQ4];
  8655. qfrq[1] = dz->fptr[QOR_FRQ1];
  8656. qfrq[2] = dz->fptr[QOR_FRQ2]; // Point to appropriate arrays storing eventual transposition of formant
  8657. qfrq[3] = dz->fptr[QOR_FRQ3];
  8658. qfrq[4] = dz->fptr[QOR_FRQ4];
  8659. // Array numbering error-check
  8660. n = 0;
  8661. offset = 6;
  8662. for(fno = 1;fno <= 4;fno++) {
  8663. qdep_param = fno+offset;
  8664. switch(fno) {
  8665. case(1): if(qdep_param != F_QDEP1) n = 1; break;
  8666. case(2): if(qdep_param != F_QDEP2) n = 1; break;
  8667. case(3): if(qdep_param != F_QDEP3) n = 1; break;
  8668. case(4): if(qdep_param != F_QDEP4) n = 1; break;
  8669. }
  8670. if(n) {
  8671. fprintf(stdout,"ERROR: Array numbering mismatch: formants_smooth_and_quantise_all() Change offset, or array numbers.\n");
  8672. return PROGRAM_ERROR;
  8673. }
  8674. }
  8675. if(dz->quantcnt) {
  8676. pstt = dz->parray[QUANTPITCH];
  8677. pend = pstt + dz->quantcnt - 1; // Initialise (for changing or unchanging) Quantisation Data
  8678. if(dz->timedhf) // Initialise end address of Time-changing Quantisation Data
  8679. abs_pend = pstt + (dz->quantcnt * dz->itemcnt) - 1;
  8680. }
  8681. fprintf(stdout,"INFO: Modifying formant paths.\n");
  8682. // For every formant-frq trace
  8683. for(fno = 1; fno <= 4; fno++) {
  8684. if(dz->timedhf) {
  8685. at_timehfend = 0;
  8686. pstt = dz->parray[QUANTPITCH];
  8687. thistime = 0.0;
  8688. pend = pstt + dz->quantcnt - 1;
  8689. if(pend >= abs_pend)
  8690. at_timehfend = 1;
  8691. else {
  8692. next_pstt = pstt + dz->quantcnt;
  8693. next_pend = next_pstt + dz->quantcnt - 1;
  8694. nexttime = *next_pstt;
  8695. }
  8696. }
  8697. // If data is to be quantised or smoothed
  8698. if(dz->quantcnt || dz->vflag[F_SMOOTH]) {
  8699. // First convert frq to MIDI
  8700. for(n=0;n < dz->wlength; n++) {
  8701. qdep_param = fno+offset;
  8702. if(dz->brksize[qdep_param]) {
  8703. time = dz->frametime * n;
  8704. if((exit_status = read_value_from_brktable(time,qdep_param,dz))<0)
  8705. return exit_status;
  8706. }
  8707. if(dz->timedhf && !at_timehfend){
  8708. time = dz->frametime * n;
  8709. if(time > nexttime) {
  8710. if(next_pstt + dz->quantcnt >= abs_pend) {
  8711. at_timehfend = 1; // At last data set of gtime-changing data.
  8712. pstt++; // Change to standard read convention, ignoring time-value
  8713. } else {
  8714. thistime = nexttime;
  8715. pstt = next_pstt;
  8716. pend = next_pend;
  8717. next_pstt += dz->quantcnt;
  8718. next_pend += dz->quantcnt;
  8719. nexttime = *next_pstt;
  8720. }
  8721. }
  8722. if(!at_timehfend)
  8723. time_ratio = (time - thistime)/(nexttime - thistime);
  8724. }
  8725. if(dz->pitches[n] < MINPITCH || ffrq[fno][n] < MINPITCH) { // pitch has been smoothed since extracting formants
  8726. qfrq[fno][n] = -1.0; // So no processing of formant-pitch, flagged at zero
  8727. continue; // so pitch window may now have been assigned a pitched but have no formant data
  8728. }
  8729. if((exit_status = hztomidi(&thismidi,ffrq[fno][n]))<0)
  8730. return(exit_status);
  8731. // If data is to be quantised, quantise it
  8732. if(dz->quantcnt && dz->param[qdep_param] > 0.0) {
  8733. if(dz->timedhf && !at_timehfend) {
  8734. qmidi1 = pitch_quantise(thismidi,pstt+1,pend,dz); // pstt is a time val: MIDI vals start at pstt+1
  8735. qmidi2 = pitch_quantise(thismidi,next_pstt+1,next_pend,dz);
  8736. qmidi = ((qmidi2 - qmidi1) * time_ratio) + qmidi1;
  8737. } else
  8738. qmidi = pitch_quantise(thismidi,pstt,pend,dz);
  8739. // and allow for quantisation depth parameter
  8740. if(dz->param[qdep_param] < 1.0) {
  8741. quantintvl = qmidi - thismidi;
  8742. quantintvl *= dz->param[qdep_param];
  8743. qmidi = thismidi + quantintvl;
  8744. }
  8745. thismidi = qmidi;
  8746. }
  8747. // and store (possibly transformed) MIDI vals in qfrq
  8748. qfrq[fno][n] = (float)thismidi;
  8749. }
  8750. // If data is to be smoothed, now smooth it
  8751. if(dz->vflag[F_SMOOTH]) {
  8752. if((exit_status = pitchline_smooth(qfrq[fno],min_wcnt,1,dz))<0)
  8753. return exit_status;
  8754. }
  8755. // Finally convert back to frq, then replace by frq-transposition value
  8756. for(n=0;n < dz->wlength; n++) {
  8757. if(qfrq[fno][n] < 0.0) // Zero pitch or zero-pitched formant
  8758. qfrq[fno][n] = 1.0f; // No transposition
  8759. else {
  8760. qfrq[fno][n] = (float)miditohz(qfrq[fno][n]); // Converted MIDI to frq
  8761. qfrq[fno][n] = qfrq[fno][n]/ffrq[fno][n]; // Convert frq to frq-transposition value
  8762. }
  8763. }
  8764. } else {
  8765. for(n=0;n < dz->wlength; n++)
  8766. qfrq[fno][n] = 1.0; // If no processing of formant-pitch, transposition value = 1.0
  8767. }
  8768. }
  8769. return FINISHED;
  8770. }
  8771. /************************** FORMANTS_SINUS ************************/
  8772. int formants_sinus(int inner_lpcnt,dataptr dz)
  8773. {
  8774. int exit_status, n, cc, vc, newcc, pkcnt, thistrof, thispeak, nexttrof, peakcc;
  8775. int preskirt_stt, postskirt_end = 0, nu_preskirt_stt, nu_postskirt_end, skirtlen, offset, famp_param = 0;
  8776. int *ftrn[9];
  8777. float *tranpos[5];
  8778. double skirting, frq, time;
  8779. double ampscale[5];
  8780. skirting = 1.0 - dz->param[F_SINING]; // F_SINING Range 0 (full formant) to 1 (sinusoid, single channel)
  8781. // Width of skirt Range 1 (all of skirt) to 0 (no skirt)
  8782. tranpos[1] = dz->fptr[QOR_FRQ1];
  8783. tranpos[2] = dz->fptr[QOR_FRQ2]; // point to arrays for formant transposition
  8784. tranpos[3] = dz->fptr[QOR_FRQ3];
  8785. tranpos[4] = dz->fptr[QOR_FRQ4];
  8786. ftrn[0] = dz->iparray[F_CHTRAIN1]; // And flbufptr channels of peaks and trofs
  8787. ftrn[1] = dz->iparray[F_CHTRAIN2];
  8788. ftrn[2] = dz->iparray[F_CHTRAIN3];
  8789. ftrn[3] = dz->iparray[F_CHTRAIN4];
  8790. ftrn[4] = dz->iparray[F_CHTRAIN5];
  8791. ftrn[5] = dz->iparray[F_CHTRAIN6];
  8792. ftrn[6] = dz->iparray[F_CHTRAIN7];
  8793. ftrn[7] = dz->iparray[F_CHTRAIN8];
  8794. ftrn[8] = dz->iparray[F_CHTRAIN9];
  8795. ampscale[1] = dz->param[F_AMP1];
  8796. ampscale[2] = dz->param[F_AMP2];
  8797. ampscale[3] = dz->param[F_AMP3];
  8798. ampscale[4] = dz->param[F_AMP4];
  8799. // Array numbering error-check
  8800. n = 0;
  8801. offset = 2;
  8802. for(pkcnt = 1;pkcnt <= 4;pkcnt++) {
  8803. famp_param = pkcnt+offset;
  8804. switch(pkcnt) {
  8805. case(1): if(famp_param != F_AMP1) n = 1; break;
  8806. case(2): if(famp_param != F_AMP2) n = 1; break;
  8807. case(3): if(famp_param != F_AMP3) n = 1; break;
  8808. case(4): if(famp_param != F_AMP4) n = 1; break;
  8809. }
  8810. if(n) {
  8811. fprintf(stdout,"ERROR: Array numbering mismatch: formants_sinus() Change offset, or array numbers.\n");
  8812. return PROGRAM_ERROR;
  8813. }
  8814. }
  8815. // Preset windowbuf to zeroamplitude, and default frequencies
  8816. for(cc = 0, vc = cc*2;cc < dz->clength;cc++,vc+=2) {
  8817. dz->windowbuf[0][AMPP] = 0.0f;
  8818. dz->windowbuf[0][FREQ] = (float)(cc * dz->chwidth);
  8819. }
  8820. pkcnt = 1;
  8821. // Copy transposed peaks (& their skirts) into windowbuf
  8822. for(n = 0;n < PKBLOK-1;n+=2) { // Going up channo-of-trof-peak data in pairs, where peaks are the 2nd items
  8823. thistrof = n;
  8824. thispeak = n+1;
  8825. nexttrof = n+2;
  8826. peakcc = ftrn[thispeak][inner_lpcnt]; // Go to the original cc channel the fpeak data was in
  8827. if(skirting > 0) {
  8828. if(n == 0) // Find the size of the peak skirts which must be transformed
  8829. preskirt_stt = ftrn[thistrof][inner_lpcnt];
  8830. else
  8831. preskirt_stt = postskirt_end;
  8832. postskirt_end = ftrn[nexttrof][inner_lpcnt];
  8833. skirtlen = peakcc - preskirt_stt;
  8834. skirtlen = (int)round(skirtlen * skirting);
  8835. nu_preskirt_stt = peakcc - skirtlen;
  8836. skirtlen = postskirt_end - peakcc;
  8837. skirtlen = (int)round(skirtlen * skirting);
  8838. nu_postskirt_end = peakcc + skirtlen;
  8839. } else {
  8840. nu_preskirt_stt = peakcc;
  8841. nu_postskirt_end = peakcc;
  8842. }
  8843. if(dz->brksize[famp_param]) {
  8844. time = dz->frametime * n;
  8845. if((exit_status = read_value_from_brktable(time,famp_param,dz))<0)
  8846. return exit_status;
  8847. } // For the peak & the remaining skirt channels
  8848. for(cc = nu_preskirt_stt, vc = cc*2;cc <= nu_postskirt_end;cc++,vc+=2) {
  8849. frq = dz->flbufptr[0][FREQ] * tranpos[pkcnt][inner_lpcnt]; // Transpose them,
  8850. newcc = (int)round(frq/(double)dz->chwidth); // put them in approp channel of windowbuf, with their orig amplitude
  8851. // Pre modify level of formants, if params set
  8852. if(ampscale[pkcnt] != 1.0)
  8853. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * ampscale[pkcnt]);
  8854. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) { // IF there's not already (new) data in that channel with a higher amplitude
  8855. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  8856. dz->windowbuf[0][newcc*2+1] = (float)frq;
  8857. }
  8858. }
  8859. pkcnt++;
  8860. }
  8861. // Replace window by transformed window
  8862. memcpy((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],dz->wanted * sizeof(float));
  8863. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  8864. for(vc=0;vc<dz->wanted;vc+=2)
  8865. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  8866. }
  8867. return FINISHED;
  8868. }
  8869. /************************** STORE_FORMANT_FRQ_DATA ************************/
  8870. int store_formant_frq_data(int inner_lpcnt,dataptr dz)
  8871. {
  8872. int exit_status, n, pkno, get_fundamental = 0, thistrof, thispeak, nexttrof, pretrof, spstt, spend, ccstt, vcstt, ccend, cc, vc, newcc;
  8873. float frqstt, frqend, the_fundamental = 0.0f, newfrq;
  8874. double maxamp, minamp;
  8875. int *peakat = dz->iparray[PEAKPOS], *ftrn[9];
  8876. float *ffrq[5];
  8877. if(dz->fundamental)
  8878. the_fundamental = dz->pitches[inner_lpcnt];
  8879. peakat += inner_lpcnt * PKBLOK; // Go to current position in peak-data array
  8880. ffrq[1] = dz->fptr[FOR_FRQ1];
  8881. ffrq[2] = dz->fptr[FOR_FRQ2]; // Point to appropriate arrays to store formant frq-data
  8882. ffrq[3] = dz->fptr[FOR_FRQ3];
  8883. ffrq[4] = dz->fptr[FOR_FRQ4];
  8884. ftrn[0] = dz->iparray[F_CHTRAIN1]; // And assciated formant-frq channel in flbufptr[0]
  8885. ftrn[1] = dz->iparray[F_CHTRAIN2];
  8886. ftrn[2] = dz->iparray[F_CHTRAIN3];
  8887. ftrn[3] = dz->iparray[F_CHTRAIN4];
  8888. ftrn[4] = dz->iparray[F_CHTRAIN5]; // And assciated formant-frq channel in flbufptr[0]
  8889. ftrn[5] = dz->iparray[F_CHTRAIN6];
  8890. ftrn[6] = dz->iparray[F_CHTRAIN7];
  8891. ftrn[7] = dz->iparray[F_CHTRAIN8];
  8892. ftrn[8] = dz->iparray[F_CHTRAIN9]; // And assciated formant-frq channel in flbufptr[0]
  8893. for(n = 0,pkno = 1; n < PKBLOK-1; n+=2,pkno++) { // Going through the trof and peaks in pairs
  8894. thistrof = n;
  8895. thispeak = n+1;
  8896. nexttrof = n+2;
  8897. spstt = peakat[n]; // Get specenvamp locations of a trof.
  8898. if(n == 0) {
  8899. if(dz->fundamental && n == 0)
  8900. get_fundamental = 1;
  8901. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  8902. frqstt = 0.0f;
  8903. else
  8904. frqstt = dz->specenvtop[spstt-1];
  8905. frqend = dz->specenvtop[spstt];
  8906. ccstt = (int)floor(frqstt/dz->chwidth);// Find the flbufpr channels associated with these frqs
  8907. ccend = (int)ceil(frqend/dz->chwidth);
  8908. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  8909. vcstt = ccstt * 2;
  8910. ftrn[thistrof][inner_lpcnt] = ccstt;
  8911. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  8912. if(dz->flbufptr[0][AMPP] < minamp) {
  8913. minamp = dz->flbufptr[0][AMPP];
  8914. ftrn[thistrof][inner_lpcnt] = cc;
  8915. }
  8916. }
  8917. }
  8918. pretrof = ftrn[thistrof][inner_lpcnt]; // if n>0, value of nexttrof in last loop pass, becomes thistrof in this pass
  8919. spend = peakat[nexttrof]; // Find specenv location of next TROF
  8920. frqstt = dz->specenvtop[spstt]; // Find the top of the frequency band associated with the lower trof
  8921. frqend = dz->specenvtop[spend - 1]; // Find the bottom of the frequency band associated with the upper trof
  8922. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  8923. ccend = (int)ceil(frqend/dz->chwidth);
  8924. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  8925. ftrn[nexttrof][inner_lpcnt] = ccstt;
  8926. for(cc = ccstt,vc = ccstt*2; cc < ccend; cc++,vc+=2) {
  8927. if(dz->flbufptr[0][AMPP] < minamp) {
  8928. minamp = dz->flbufptr[0][AMPP];
  8929. ftrn[nexttrof][inner_lpcnt] = cc;
  8930. }
  8931. }
  8932. ccstt = pretrof; // Search between these trofs, for the peak
  8933. ccend = ftrn[nexttrof][inner_lpcnt];
  8934. maxamp = -HUGE; // Find flbufptr location of PEAK amplitude between these trofs
  8935. ftrn[thispeak][inner_lpcnt] = ccstt;
  8936. for(cc = ccstt,vc = ccstt*2; cc < ccend; cc++,vc+=2) {
  8937. if(dz->flbufptr[0][AMPP] > maxamp) {
  8938. maxamp = dz->flbufptr[0][AMPP];
  8939. ffrq[pkno][inner_lpcnt] = dz->flbufptr[0][FREQ];
  8940. ftrn[thispeak][inner_lpcnt] = cc;
  8941. }
  8942. }
  8943. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  8944. if(the_fundamental > 0.0) {
  8945. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  8946. return exit_status;
  8947. ffrq[pkno][inner_lpcnt] = newfrq;
  8948. ftrn[thispeak][inner_lpcnt] = newcc;
  8949. }
  8950. get_fundamental = 0; // Only (try to) get fundamental when in first formant
  8951. }
  8952. }
  8953. return FINISHED;
  8954. }
  8955. /************************** PITCHLINE_SMOOTH ************************/
  8956. int pitchline_smooth(float *pichline,int min_wcnt,int ismidi,dataptr dz)
  8957. {
  8958. float previouspitch, thispitch;
  8959. double minpitch;
  8960. int n, m, k, wcnt;
  8961. if(ismidi)
  8962. minpitch = MINPITCHMIDI;
  8963. else
  8964. minpitch = MINPITCH;
  8965. previouspitch = -1;
  8966. wcnt = 0;
  8967. for(n = 0; n < dz->wlength-1; n++) {
  8968. if(pichline[n] < minpitch) // Find the next pitch
  8969. continue; // and start a count of the number of windows it persists for
  8970. thispitch = pichline[n];
  8971. wcnt = 1;
  8972. for(m = n+1; m < dz->wlength; m++) { // Look at block of pitches beyond "thispitch"...
  8973. if(pichline[m] < minpitch) { // If we hit an unpitched area
  8974. if(wcnt < min_wcnt) { // IF there were not enough windows in the block of pitch
  8975. if(previouspitch > 0.0) { // Set them equal to the preceeding pitch (if there is one)
  8976. for(k = n; k < m; k++)
  8977. pichline[k] = previouspitch;
  8978. }
  8979. } else // Else they were a valid block
  8980. previouspitch = thispitch; // Set this pitch up as the previouspitch for next search
  8981. break; // Outer loop will now skip this no-pitch window and proceed
  8982. } // Break to get next pitch;
  8983. if(pichline[m] == thispitch) // If still on same pitch, count it
  8984. wcnt++; // Else
  8985. else {
  8986. if(wcnt < min_wcnt) { // If we don't have valid wcnt for this pitch
  8987. if(previouspitch > 0.0) { // set it equal to the previous pitch
  8988. for(k = n; k < m; k++)
  8989. pichline[k] = previouspitch;
  8990. }
  8991. }
  8992. break; // break to the outer loop
  8993. }
  8994. }
  8995. if(m == dz->wlength) { // If we didn't break from inner loop
  8996. if(wcnt < min_wcnt) { // If last block of pitch doesn't have valid wcnt for this pitch
  8997. if(previouspitch > 0.0) { // set it equal to the previous pitch
  8998. for(k = n; k < m; k++)
  8999. pichline[k] = previouspitch;
  9000. }
  9001. }
  9002. }
  9003. n = m-1; // forces window we've reached to be caught in outer loop
  9004. }
  9005. return FINISHED;
  9006. }
  9007. /************************** SMOOTH_NOTE_TO_NOTE_TRANSITIONS ************************/
  9008. int smooth_note_to_note_transitions(float *pichline,dataptr dz)
  9009. {
  9010. double pitchstep;
  9011. float thispitch;
  9012. int n, m, j, k;
  9013. int glide_wins = (int)round(PCHANGE_DUR/dz->frametime);
  9014. for(n = 0; n < dz->wlength-1; n++) {
  9015. if(pichline[n] < MINPITCH) // Find the next pitch
  9016. continue; // and start a count of the number of windows it persists for
  9017. thispitch = pichline[n];
  9018. for(m = n+1; m < dz->wlength; m++) { // Look at block of pitches beyond "thispitch"...
  9019. if(pichline[m] != thispitch) { // If we hit a new pitch or an unpitched area
  9020. if(pichline[m] > MINPITCH && m > glide_wins) { // if in new pitch area, and enough windows available todo pitch-glide
  9021. pitchstep = pichline[m] - thispitch; // Get step in pitch
  9022. pitchstep /= (double)(glide_wins+1); // i.e. If 4 wins in transit, these step by 1/5 2/5 3/5 and 4/5 of total pitchstep
  9023. for(j= 1,k=m-glide_wins;k < m;j++,k++)
  9024. pichline[k] = (float)(pichline[k] + (pitchstep * j));
  9025. }
  9026. break; // break to the outer loop
  9027. }
  9028. }
  9029. n = m-1;
  9030. }
  9031. return FINISHED;
  9032. }
  9033. /************************** OCTAVIATE_TIMED_HF_DATA ************************/
  9034. int octaviate_and_store_timed_hf_data(dataptr dz)
  9035. {
  9036. int n, m, j;
  9037. double *pset = dz->parray[QUANTPITCH], *prepitch = dz->parray[PREPICH];
  9038. double nextpitch;
  9039. double octstep;
  9040. int loc = 0, pitchpos = 0;
  9041. for(n=0;n < dz->bincnt;n++) // Preset the array to max possible quantisation value
  9042. pset[n] = MIDIMAX;
  9043. for(n = 0; n < dz->itemcnt; n++) { // For every line of entries
  9044. if(pitchpos >= dz->bincnt) {
  9045. sprintf(errstr,"Array overflow 1 in octaviate_and_store_timed_hf_data()\n");
  9046. return PROGRAM_ERROR;
  9047. }
  9048. pset[pitchpos++] = prepitch[loc]; // Copy time of pitch-set
  9049. octstep = 0.0;
  9050. for(m=0;m < MIDIOCTSPAN; m++) { // For evey octave in the MIDI range
  9051. for(j = 1;j < dz->quantcnt;j++) { // For every PITCH entry in the line
  9052. nextpitch = prepitch[loc+j] + octstep; // Get entry and add octstep
  9053. nextpitch = min(nextpitch,MIDIMAX);
  9054. if(pitchpos >= dz->bincnt) {
  9055. sprintf(errstr,"Array overflow 2 in octaviate_and_store_timed_hf_data()\n");
  9056. return PROGRAM_ERROR;
  9057. }
  9058. pset[pitchpos++] = nextpitch; // copy new pitch into final array
  9059. }
  9060. octstep += SEMITONES_PER_OCTAVE;
  9061. }
  9062. loc += dz->quantcnt; // Go to next set of original entries
  9063. }
  9064. dz->quantcnt--; // No of quantising items in one timed HF before octaviation
  9065. dz->quantcnt *= MIDIOCTSPAN; // No of quantising items in one timed HF after octaviation
  9066. dz->quantcnt++; // With the time value
  9067. return FINISHED;
  9068. }
  9069. /************************** STRIP_END_SPACE ************************/
  9070. void strip_end_space(char *p)
  9071. {
  9072. char *q = p;
  9073. while(*p != ENDOFSTR)
  9074. p++;
  9075. p--;
  9076. while(isspace(*p)) {
  9077. *p = ENDOFSTR;
  9078. p--;
  9079. if(p == q)
  9080. break;
  9081. }
  9082. return;
  9083. }