specfnu.c 442 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805
  1. /*
  2. * Copyright (c) 1983-2013 Trevor Wishart and Composers Desktop Project Ltd
  3. * http://www.trevorwishart.co.uk
  4. * http://www.composersdesktop.com
  5. *
  6. This file is part of the CDP System.
  7. The CDP System is free software; you can redistribute it
  8. and/or modify it under the terms of the GNU Lesser General Public
  9. License as published by the Free Software Foundation; either
  10. version 2.1 of the License, or (at your option) any later version.
  11. The CDP System is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU Lesser General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public
  16. License along with the CDP System; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
  18. 02111-1307 USA
  19. *
  20. */
  21. /*
  22. SEE FILE temp.cpp for pitch-modification originals to import here!!!!
  23. _cdprogs\specfnu specfnu 23 alan_bellydancefbn.ana test.wav hague_trials\triadhf.txt 1 -n1 -o1 -p1 -q1 -S
  24. Spectral channels are dz->specenvamp && dz->specenvfrq
  25. dz->specenvamp[0] = (float)0.0;
  26. dz->specenvfrq[0] = (float)1.0;
  27. frqstep = dz->halfchwidth * (double)dz->formant_bands;
  28. Defaulting to 12 so we get a spectral channel widtth of c 260hz (and smaller window option give 86Hz bands)
  29. */
  30. //#define SEECHANGE 1
  31. #include <stdio.h>
  32. #include <stdlib.h>
  33. #include <structures.h>
  34. #include <tkglobals.h>
  35. #include <pnames.h>
  36. #include <filetype.h>
  37. #include <processno.h>
  38. #include <modeno.h>
  39. #include <logic.h>
  40. #include <globcon.h>
  41. #include <cdpmain.h>
  42. #include <formants.h>
  43. #include <math.h>
  44. #include <mixxcon.h>
  45. #include <osbind.h>
  46. #include <standalone.h>
  47. #include <science.h>
  48. #include <speccon.h>
  49. #include <ctype.h>
  50. #include <sfsys.h>
  51. #include <string.h>
  52. #include <srates.h>
  53. #ifdef unix
  54. #define round lround
  55. #endif
  56. #ifndef HUGE
  57. #define HUGE 3.40282347e+38F
  58. #endif
  59. #define VIEWSCALE (1.0e3) // Multiplier enabling pvoc amplitudes to be easily read in any on-screen debug print
  60. #define warned is_rectified
  61. #define pktrofcnt rampbrksize
  62. #define xclude_nonh temp_sampsize
  63. #define badpks fzeroset
  64. #define suprflag unspecified_filecnt // Used by F_SUPPRESS and F_NARROW
  65. #define timedhf unspecified_filecnt // Used by F_SINUS
  66. #define phasefactor is_flat
  67. #define bincnt different_srates
  68. #define quantcnt finished
  69. #define in_tune is_sharp
  70. #define fundamental numsize
  71. #define avfrq maxnum
  72. #define timeblokcnt sampswanted
  73. #define ischange could_be_transpos
  74. #define shortwins duplicate_snds
  75. #define frq_step scalefact
  76. #define needpitch could_be_pitch
  77. #define fsil_ratio minnum
  78. #define retain_unpitched_data_for_deletion is_transpos
  79. // PROCESSING PASSES
  80. #define FPREANAL 0
  81. #define FSPECENV 1
  82. #define FPROCESS 2
  83. // ARRAY NAMES
  84. // integer array names
  85. #define PEAKPOS 0 // iparray[0]
  86. #define PCNTBIN 1 // iparray[1]
  87. #define FCNT 2 // iparray[2]
  88. #define ISHARM 3 // iparray[3]
  89. #define IARRAYCNT 4 // Number of iparrays
  90. #define F_CHTRAIN1 4
  91. #define F_CHTRAIN2 5
  92. #define F_CHTRAIN3 6
  93. #define F_CHTRAIN4 7
  94. #define F_CHTRAIN5 8
  95. #define F_CHTRAIN6 9
  96. #define F_CHTRAIN7 10
  97. #define F_CHTRAIN8 11
  98. #define F_CHTRAIN9 12
  99. #define IBIGARRAYCNT 13 // Number of iparrays
  100. // double array names
  101. #define PBINPCH 1 // parray[1] pitch extraction
  102. #define PBINTOP 2 // parray[2]
  103. #define PBINAMP 3 // parray[3]
  104. #define PREPICH 4 // parray[4] sorting input pitch data
  105. #define QUANTPITCH 5 // parray[5] pitch quantisation
  106. #define FILTPICH 5 // parray[5] filter design
  107. #define FILTAMP 6 // parray[6]
  108. #define LOCALPCH 7 // parray[7]
  109. #define LOCALAMP 8 // parray[8]
  110. #define FMULT 9 // parray[9] concatenation of moving formants
  111. #define FPITCHES 9 // parray[9] All pitches actually used by varibank filter
  112. #define FSPEC3 10 // parray[10]
  113. #define PRE_P_ARRAYCNT 11 // Total number of arrays, excluding arrays needed for pitch extraction
  114. #define P_PRETOTAMP 11 // parray[11] loudness envelope extraction (and pitch-smoothing)
  115. #define RUNNINGAVRG 12 // parray[12] pitch smoothing
  116. #define RUNAVGDURS 13 // parray[13]
  117. #define F_PINTMAP 14 // parray[14] stores interval-map for pitch-inversion over HFs
  118. #define TOT_DBLARRAYCNT 15 // Total number of double arrays
  119. // float array names
  120. // spec peaks-and-trofs data
  121. #define PKTROF 0 // fptr[0] peaks-and-trofs
  122. #define PKDIFF 1 // fptr[1] peak-trof differences
  123. // filter-line storage for varibank filter data in F_MAKEFILT
  124. #define FILTLINE 2 // fptr[2]
  125. #define LASTFLINE 3 // fptr[3]
  126. // peaks-and-trofs data for moved formants
  127. #define FAMP1 2 // fptr[2]
  128. #define FAMP2 3 // fptr[3]
  129. #define FAMP3 4 // fptr[4]
  130. #define FAMP4 5 // fptr[5]
  131. #define FFRQ1 6 // fptr[6]
  132. #define FFRQ2 7 // fptr[7]
  133. #define FFRQ3 8 // fptr[8]
  134. #define FFRQ4 9 // fptr[9]
  135. #define FPCH1 10 // fptr[10]
  136. #define FPCH2 11 // fptr[11]
  137. #define FPCH3 12 // fptr[12]
  138. #define FPCH4 13 // fptr[13]
  139. // arrays for storing formant pitch data
  140. #define FOR_FRQ1 2 // Alternative names
  141. #define FOR_FRQ2 3 // for same arrays
  142. #define FOR_FRQ3 4 // when used by
  143. #define FOR_FRQ4 5 // F_SINUS
  144. #define QOR_FRQ1 6
  145. #define QOR_FRQ2 7
  146. #define QOR_FRQ3 8
  147. #define QOR_FRQ4 9
  148. #define P_SINUS_ARRAYS 8// Number of arrays used in storing and manipulating formant pitch-streams:
  149. // from F_AMP1 to QOR_FRQ4
  150. #define PKSARRAYCNT 14 // Number of float arrays for dealing with peak/trof detection & moving formants
  151. // harmonics detection
  152. #define HMNICBOUNDS 14 // fptr[14]
  153. // contour extraction
  154. #define CONTOURFRQ 15 // fptr[15]
  155. #define CONTOURPCH 16 // fptr[16]
  156. #define CONTOURAMP 17 // fptr[17]
  157. #define CONTOURTOP 18 // fptr[18]
  158. #define CONTOURAMP2 19 // fptr[19]
  159. #define TOTAL_FLARRAYCNT 20 // Total number of float array
  160. // int arrays
  161. #define FTIMES 0 // lparray[0] Counting time-breaks in building filter : F_MAKEFILT
  162. #define AVSTT 1 // lparray[1] Counting during continuity_smoothing of pitch data
  163. #define TOTAL_LPARRAYCNT 2 // Total number of int arrays
  164. // ESTABLISHING FORMANT BANDS AMD CONTOUR ENVELOPE SIZE
  165. #define SPECFNU_SHORT_FBANDS 4 //
  166. #define SPECFNU_FBANDS 12 // Choose value to give best peak separation (but not too many peaks) This is no of HAlF channel-widths
  167. #define SPECFNU_LONG_FBANDS 72
  168. #define CLENGTH_DEFAULT 512 // Default number of analysis points (AP): AP determines window-width,
  169. // NO OF PEAKS + TROFS TO STORE
  170. #define PKBLOK 9 // 5 trofs and 4 peaks = 9 points
  171. // DETECTION OF FUNDAMENTAL
  172. #define TWO_OVER_THREE 0.6666
  173. // DETECTION OF HARMONICS
  174. #define WITHIN_RANGE 1 // Semitone range for a partial to be considered a fundamental of the peak harmonic (or vice versa)
  175. // PITCH PROCESSING
  176. #define FMAXIMI (8) // No of (max) peaks to use to check for harmonicity
  177. #define FCHANSCAN (8) // No of channels to scan looking for equivalent pitches at possible peak
  178. #define FPEAK_LIMIT (.05)
  179. #define MAXIMUM_PARTIAL (64) // Maximum partial to search for
  180. #define ALMOST_TWO (1.5) // Approximating 8ve leaps, when looking for 8va leap anomalies
  181. #define EIGHT_OVER_SEVEN (1.142857143) // Intervals within which pitch is "close" to existing frequency
  182. #define SEVEN_OVER_EIGHT (0.875)
  183. #define GOOD_MATCH (5) // No of peaks that must be harmonics for window to register as pitched
  184. #define FBLIPLEN (2) // Number of adjacent windows that must be pitched for pitch not to be spurious is MORE THAN FBLIPLEN
  185. #define FSILENCE_RATIO (42) // Any window falling SILENCE_RATIO dBs below maximum window-level assumed to be "silence"
  186. #define FPICH_HILM (dz->nyquist/FMAXIMI)//High limit of pitch to search for (as we need FMAXIMI peaks to search for pitch)
  187. #define FMIN_SMOOTH_SET (3) // Minimum number of adjacent smooth pitches to imply true pitch present
  188. #define FMAX_GLISRATE (16.0) // Assumptions: pitch can't move faster than 16 octaves per sec: FMAX_GLISRATE
  189. // Possible movement from window-to-window = FMAX_GLISRATE * dz->frametime
  190. #define VOICEHI (1500.0) // F# above C 2 8vas abive middle C
  191. #define MVOICEHI (500) // B above middle C
  192. #define VOICELO (48.0) // G below C 2 8vas below middle C
  193. // PITCH INTERPOLATION
  194. #define FMID_PITCH (0)
  195. #define FFIRST_PITCH (1)
  196. #define FEND_PITCH (2)
  197. #define FNO_PITCH (3)
  198. #define TOO_SHORT_PICH (0.1) // Segment of pitchedness within line must be longer than this, to register
  199. #define TOO_SHORT_UNPICH (0.05) // Segment of unpitchedness within line must be longer than this, to register
  200. // SPECTRUM PITCH-TRANSPOSITION
  201. #define FSPEC_MINFRQ (9.0)
  202. // F_SEE
  203. #define SPECFNU_MAXLEVEL (0.95) // Max level for normalisation
  204. #define SPECFNU_BLOKCNT 7 // Number of samples of equal value forming a block for display in output of F_SEE
  205. // F_NARROW
  206. #define F4_ZEROED 8 // Last formant(4) being zeroed is flagged by 4th bit in suprflag (1000) = 8
  207. // F_MAKEFILE
  208. #define MIDIOCTSPAN 11 // 0-127 = 10 octaves (120) + 7semitones. so 11 octaves spans the range
  209. #define MINWINDOWS 60 // Min no of windows over which a filter can be defined
  210. #define FILTER_STAGGER 0.05 // Time between filter settings, when filters change
  211. #define FILTER_BAD_LEAP (SEMITONES_PER_OCTAVE * 1.5)
  212. // F_MOVE(2)
  213. #define F_LOFRQ_LIMIT (1.0)
  214. #define F_HIFRQ_LIMIT (dz->nyquist/2.0)
  215. // F_SYLABTROF
  216. // COLORING ARPEGGIATION
  217. #define ARPEG_RANGE 7.0 // Total number of partials being arpeggiated is 8 (i.e 0 to 7)
  218. #define ARPEG_WIN_WIDTH 4.0 // Number of partials under highlighting window
  219. #define ARPEG_WIN_HALFWIDTH (ARPEG_WIN_WIDTH/2.0) // Halfwifth highlighting window
  220. // SLOPE OF TAILOFF OF EXTRA PARTIALS ADDED AT SPECTRUM TOP
  221. #define TAILOFF_SLOPE 4.0
  222. #define INTERVAL_MAPPING (29) /* FILE OR VAL */ /* special_data : Map interval-->interval for spec pinvert */
  223. #define PSEUDOCTMIN (4) // Size range, in semitones, of any pseudo_octave used in tuning, or quantiosation spec
  224. #define PSEUDOCTMAX (48)
  225. #define MAXSCALECNT (100) // Max number of divisions of octave, in tuning data
  226. #define VERY_SMOOTH (0.3) // Very smooth pitchline
  227. #define STABLE_DUR (0.2) // Min duration of (quantised) pitch, which is NOT an ornament
  228. #define ORNAMENT_DUR (0.1) // Min duration of (quantised) pitch, which could be an ornament
  229. #define PCHANGE_DUR (0.05) // Time to shift pitch from one pitch to another
  230. #define PRAND_TRANGE (2.0) // Time-slot where rand-val of pitch-variation stays fixed, ranges from a minimum TO (min + 2*min)
  231. #define PRAND_TSTEP (0.05)
  232. #define PRAND_ORN_TSTEP (0.015)
  233. #define MINPITCHMIDI (1.662783) // MIDI val corresponding to MINPITCH
  234. // formant frequencies and amplitudes for 1st 3 formants : might be useful : NOT USED as at MAY 15: 2016
  235. #if 0
  236. static double heed[6] = {300,2600,2800,1.0,0.85,0.85};
  237. static double hid[6] = {360,2100,2300,1.0,1.0, 1.0 };
  238. static double educAtedScot[6] = {500,2250,2450,1.0,0.92,0.25};
  239. static double laid[6] = {465,2250,2450,1.0,0.92,0.25};
  240. static double head[6] = {570,1970,2450,1.0,1.0, 0.75};
  241. static double had[6] = {750,1550,2450,1.0,1.0, 0.85};
  242. static double hard[6] = {680,1100,2450,1.0,1.0, 0.92};
  243. static double hod[6] = {600,900, 2450,1.0,1.0, 0.5 };
  244. static double horde[6] = {450,860, 2300,1.0,1.0, 0.82};
  245. static double cokeNorthern[6] = {410,810, 2300,1.0,1.0, 0.82};
  246. static double mudNorthern[6] = {380,850, 2100,1.0,1.0, 0.6 };
  247. static double youscots[6] = {380,850, 2800,1.0,0.85,0.85};
  248. static double couldscots[6] = {380,1000,2450,1.0,0.92,0.25};
  249. static double mood[6] = {300,850, 2100,1.0,1.0, 0.6 };
  250. static double hubSouthern[6] = {720,1240,2300,1.0,0.85,0.3 };
  251. static double herd[6] = {580,1380,2450,1.0,1.0, 0.5 };
  252. static double nnn[6] = {580,1380,2625,1.0,0.0, 0.1 };
  253. static double mmmm[6] = {580,850, 2100,1.0,0.0, 0.0 };
  254. static double rrrflat[6] = {880,2100,2450,1.0,0.2, 0.0 };
  255. static double ththth[6] = {400,1000,2450,1.0,0.3, 0.2 };
  256. #endif
  257. char errstr[2400];
  258. int anal_infiles = 1;
  259. int sloom = 0;
  260. int sloombatch = 0;
  261. const char* cdp_version = "8.0.1";
  262. /* CDP LIBRARY FUNCTIONS TRANSFERRED HERE */
  263. static int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist);
  264. static int set_vflgs(aplptr ap,char *optflags,int optcnt,char *optlist,
  265. char *varflags,int vflagcnt, int vparamcnt,char *varlist);
  266. static int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz);
  267. static int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz);
  268. static int mark_parameter_types(dataptr dz,aplptr ap);
  269. static int establish_application(dataptr dz);
  270. static int application_init(dataptr dz);
  271. static int initialise_vflags(dataptr dz);
  272. static int setup_input_param_defaultval_stores(int tipc,aplptr ap);
  273. static int setup_and_init_input_param_activity(dataptr dz,int tipc);
  274. static int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q);
  275. static int assign_file_data_storage(int infilecnt,dataptr dz);
  276. /* CDP LIB FUNCTION MODIFIED TO AVOID CALLING setup_particular_application() */
  277. static int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz);
  278. /* SIMPLIFICATION OF LIB FUNC TO APPLY TO JUST THIS FUNCTION */
  279. static int parse_infile_and_check_type(char **cmdline,dataptr dz);
  280. static int handle_the_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz);
  281. static int setup_the_application(dataptr dz);
  282. static int setup_the_param_ranges_and_defaults(dataptr dz);
  283. static int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz);
  284. static int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt);
  285. static int get_the_mode_no(char *str, dataptr dz);
  286. static int check_specfnu_param_validity_and_consistency(dataptr dz);
  287. static int new_inner_loop(int windows_in_buf,double *fmax,int passno,int limit,int *inner_lpcnt,double *phase,int *times_index,
  288. double *target,int *previouspk,int contourcnt,int arp_param,int *up,double minpitch,double maxpitch,dataptr dz);
  289. static int set_the_specenv_frqs(int arraycnt,dataptr dz);
  290. /* BYPASS LIBRARY GLOBAL FUNCTION TO GO DIRECTLY TO SPECIFIC APPLIC FUNCTIONS */
  291. static void force_extension(int type,char *filename);
  292. static int outer_specfnu_loop(int contourcnt,dataptr dz);
  293. static int setup_formant_arrays(int *contourcnt,dataptr dz);
  294. static int formants_narrow(int inner_lpcnt,dataptr dz);
  295. static int formants_squeeze(int inner_lpcnt,dataptr dz);
  296. static int formants_invert(int inner_lpcnt,double *phase,int contourcnt,dataptr dz);
  297. static int formants_rotate(int inner_lpcnt,double *phase,dataptr dz);
  298. static int formants_see(dataptr dz);
  299. static int formants_seepks(dataptr dz);
  300. static int formants_negate(int contourcnt,dataptr dz);
  301. static int formants_suppress(int inner_lpcnt,dataptr dz);
  302. static int formants_makefilt(int inner_lpcnt,int *times_index,dataptr dz);
  303. static int formants_move(int inner_lpcnt,dataptr dz);
  304. //static int get_the_formant_sample_points(dataptr dz);
  305. static int specfnu_preprocess(dataptr dz);
  306. static int initialise_peakstore(dataptr dz);
  307. static int get_peaks_and_trofs(int inner_lpcnt,int limit,int *previouspk,dataptr dz);
  308. static int usage4(int mode);
  309. static int get_fmax(double *fmax,dataptr dz);
  310. static int handle_the_makefilt_special_data(char *str,dataptr dz);
  311. static int handle_the_pquantise_special_data(char *str,dataptr dz);
  312. static int sort_pitches(dataptr dz);
  313. static int build_filter(int times_index,dataptr dz);
  314. static int find_fundamental(float thisfrq,double target,int peakcc,float *newfrq,dataptr dz);
  315. static int equivalent_pitches(double frq1, double frq2, dataptr dz);
  316. static int move_formant(int fno,double frqoffset,int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp,float hitorfamp,int *truecnt,dataptr dz);
  317. static int concatenate_moved_formants(dataptr dz);
  318. static int edgefade_formant(float *thisfrq,float *thisamp,float *thispch,int hi,
  319. int *nuchanlen, int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp, float hitrofamp,float frqlimit,dataptr dz);
  320. static int getspecenv3amp(double frq,double *amp,float *thispch,float *thisamp,int speccnt,dataptr dz);
  321. static int fwindow_size(dataptr dz);
  322. // PITCH RELATED PROCESSING
  323. static int locate_channel_of_fundamental(int inner_lpcnt,float *fundfrq, int *newcc,dataptr dz);
  324. static int continuity_smoothing(dataptr dz);
  325. // FIND PITCH
  326. static int initialise_pitchwork(int is_launched,dataptr dz);
  327. static int establish_arrays_for_pitchwork(dataptr dz);
  328. static int specpitch(int inner_lpcnt,double *target,dataptr dz);
  329. static int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz);
  330. static int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz);
  331. static int insert_in_ring(int vc, chvptr here, dataptr dz);
  332. static int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz);
  333. static int found_pitch(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,double *thepitch,dataptr dz);
  334. //static int found_pitch_1(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,dataptr dz);
  335. //static int found_pitch_2(chvptr *partials,dataptr dz);
  336. static int smooth_spurious_octave_leaps(int pitchno,float minamp,dataptr dz);
  337. static int equivalent_pitches(double frq1, double frq2, dataptr dz);
  338. static int is_peak_at(double frq,int window_offset,float minamp,dataptr dz);
  339. static int enough_partials_are_harmonics(chvptr *partials,double thepitch,dataptr dz);
  340. static int is_equivalent_pitch(double frq1,double frq2,dataptr dz);
  341. static int is_above_equivalent_pitch(double frq1,double frq2,dataptr dz);
  342. //static int do_smooth(int n, double *slopechange,dataptr dz);
  343. static int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz);
  344. static int locate_channel_of_pitch(int inner_lpcnt,float thepitch, int *newcc,dataptr dz);
  345. // MASSAGE PITCH DATA
  346. static int tidy_up_pitch_data(dataptr dz);
  347. static int anti_noise_smoothing(int wlength,float *pitches,float frametime);
  348. static int is_smooth_from_both_sides(int n,double max_pglide,float *pitches);
  349. static int is_initialpitch_smooth(char *smooth,double max_pglide,float *pitches);
  350. static int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,float *pitches);
  351. static int is_smooth_from_before(int n,char *smooth,double max_pglide,float *pitches);
  352. static int is_smooth_from_after(int n,char *smooth,double max_pglide,float *pitches);
  353. static int test_glitch_sets(char *smooth,double max_pglide,int wlength,float *pitches);
  354. static void remove_unsmooth_pitches(char *smooth,int wlength,float *pitches);
  355. static int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,float *pitches);
  356. static int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,
  357. double max_pglide,int wlength,float *pitches);
  358. static int eliminate_blips_in_pitch_data(dataptr dz);
  359. static int mark_zeros_in_pitchdata(dataptr dz);
  360. static int pitch_found(dataptr dz);
  361. static int averages_smooth(int bracketed,int bracket,int runavcnt,dataptr dz);
  362. // INTERPOLATE PITCH DATA
  363. static int interpolate_pitch(dataptr dz);
  364. static int do_interpolating(int *pitchno,int skip_silence,dataptr dz);
  365. static double hz_to_pitchheight(double frqq);
  366. static double pitchheight_to_hz(double pitch_height);
  367. // OTHER PITCH-RELATED FUNCTIONS
  368. static int exclude_non_harmonics(dataptr dz);
  369. static int shufflup_harmonics_bounds(int *top_hno,float the_fundamental,int boundscnt,dataptr dz);
  370. static int channel_holds_harmonic(float the_fundamental,float frq,int cc,int *top_hno,dataptr dz);
  371. static int initialise_contourenv(int *contourcnt,int contourbands,dataptr dz);
  372. static int extract_contour(int contourcnt,dataptr dz);
  373. static int getcontouramp(double *thisamp,int contourcnt,double thisfrq,dataptr dz);
  374. static int suppress_harmonics(dataptr dz);
  375. static int getcontouramp2(double *thisamp,int contourcnt,double thisfrq,dataptr dz);
  376. static int remember_contouramp(int contourcnt,dataptr dz);
  377. static int trof_detect(dataptr dz);
  378. static void zero_spectrum_top(int cc,dataptr dz);
  379. static int is_coloring(dataptr dz);
  380. static int formants_recolor(int inner_lpcnt,double *phase,int *up,int arp_param,double minpitch,double maxpitch,int contourcnt,dataptr dz);
  381. static int arpeggiate(double *arpegamp,float frq,double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int is_split,dataptr dz);
  382. static int find_and_change_partials(float the_fundamental,float newfrq,int *isharm,double frqshift,double frqtrans,double randomisation,
  383. double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int do_arpegg,int is_split,dataptr dz);
  384. static int do_top_of_spectrum_fill(int cc,float endamp,float the_fundamental,double frqtrans,double frqshift,int *tail,dataptr dz);
  385. static int getmeanpitch(double *meanpitch,double *minpitch,double *maxpitch,dataptr dz);
  386. static int interval_mapping(double *thisint,double thismidi,dataptr dz);
  387. static int read_interval_mapping(char *str,dataptr dz);
  388. static int get_and_count_data_from_textfile(char *filename,double **brktable,dataptr dz);
  389. static int exag_pitchline(float *newfrq,float thisfrq,double minpich,double maxpich,dataptr dz);
  390. static int pitch_invert(float *newfrq,float the_fundamental,dataptr dz);
  391. static int pitch_quantise_all(dataptr dz);
  392. static double pitch_quantise(double thismidi,double *pstt, double *pend,dataptr dz);
  393. static int pitch_smooth(dataptr dz);
  394. static int pitch_randomise_all(dataptr dz);
  395. static int get_rand_interval(double *thisintv,dataptr dz);
  396. static int randomise_pitchblok(int start_win,int min_wcnt,int *newwcnt,dataptr dz);
  397. static int quantise_randomise_pitchblok(int n,int wcnt,double *pstt,double *pend,dataptr dz);
  398. static int formants_smooth_and_quantise_all(dataptr dz);
  399. static int formants_sinus(int inner_lpcnt,dataptr dz);
  400. static int store_formant_frq_data(int inner_lpcnt,dataptr dz);
  401. static int pitchline_smooth(float *pichline,int min_wcnt,int ismidi,dataptr dz);
  402. static int smooth_note_to_note_transitions(float *pichline,dataptr dz);
  403. static int sort_pitches_for_tvary_hf(int entrycnt,int linecnt,dataptr dz);
  404. static int octaviate_and_store_timed_hf_data(dataptr dz);
  405. static void strip_end_space(char *p);
  406. /**************************************** MAIN *********************************************/
  407. int main(int argc,char *argv[])
  408. {
  409. int exit_status, n;
  410. dataptr dz = NULL;
  411. char **cmdline;
  412. int cmdlinecnt, k;
  413. // aplptr ap;
  414. int is_launched = FALSE;
  415. int contourcnt = 0;
  416. if(argc==2 && (strcmp(argv[1],"--version") == 0)) {
  417. fprintf(stdout,"%s\n",cdp_version);
  418. fflush(stdout);
  419. return 0;
  420. }
  421. /* CHECK FOR SOUNDLOOM */
  422. if((sloom = sound_loom_in_use(&argc,&argv)) > 1) {
  423. sloom = 0;
  424. sloombatch = 1;
  425. }
  426. if(sflinit("cdp")){
  427. sfperror("cdp: initialisation\n");
  428. return(FAILED);
  429. }
  430. /* SET UP THE PRINCIPLE DATASTRUCTURE */
  431. if((exit_status = establish_datastructure(&dz))<0) { // CDP LIB
  432. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  433. return(FAILED);
  434. }
  435. if(!sloom) {
  436. if(argc == 1) {
  437. usage1();
  438. return(FAILED);
  439. } else if(argc == 2) {
  440. usage2(argv[1]);
  441. return(FAILED);
  442. } else if(argc == 3) {
  443. usage3(argv[1],argv[2]);
  444. return(FAILED);
  445. }
  446. if((exit_status = make_initial_cmdline_check(&argc,&argv))<0) { // CDP LIB
  447. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  448. return(FAILED);
  449. }
  450. cmdline = argv;
  451. cmdlinecnt = argc;
  452. if((get_the_process_no(argv[0],dz))<0)
  453. return(FAILED);
  454. cmdline++;
  455. cmdlinecnt--;
  456. dz->maxmode = 23;
  457. if(cmdlinecnt <= 0) {
  458. sprintf(errstr,"Too few commandline parameters.\n");
  459. return(FAILED);
  460. }
  461. if((get_the_mode_no(cmdline[0],dz))<0) {
  462. if(!sloom)
  463. fprintf(stderr,"%s",errstr);
  464. return(FAILED);
  465. }
  466. cmdline++;
  467. cmdlinecnt--;
  468. exit_status = CONTINUE;
  469. switch(dz->mode) {
  470. case(F_NEGATE): // fall thro
  471. case(F_SEE): // fall thro
  472. case(F_SYLABTROF): // fall thro
  473. case(F_SEEPKS): if(cmdlinecnt < 2) exit_status = FAILED; break;
  474. case(F_NARROW): // fall thro
  475. case(F_ROTATE): // fall thro
  476. case(F_SUPPRESS): // fall thro
  477. case(F_ARPEG): // fall thro
  478. case(F_OCTSHIFT): // fall thro
  479. case(F_TRANS): // fall thro
  480. case(F_FRQSHIFT): // fall thro
  481. case(F_RESPACE): // fall thro
  482. case(F_PINVERT): // fall thro
  483. case(F_PQUANT): // fall thro
  484. case(F_RAND): // fall thro
  485. case(F_INVERT): if(cmdlinecnt < 3) exit_status = FAILED; break;
  486. case(F_PEXAGG): // fall thro
  487. case(F_SINUS): // fall thro
  488. case(F_MAKEFILT): // fall thro
  489. case(F_SQUEEZE):if(cmdlinecnt < 4) exit_status = FAILED; break;
  490. case(F_PCHRAND):if(cmdlinecnt < 5) exit_status = FAILED; break;
  491. case(F_MOVE2): // fall thro
  492. case(F_MOVE): if(cmdlinecnt < 6) exit_status = FAILED; break;
  493. default:
  494. fprintf(stderr,"Unknown mode (%d) at 2nd usage check.\n",dz->mode+1);
  495. return PROGRAM_ERROR;
  496. }
  497. if(exit_status == FAILED) {
  498. usage4(dz->mode);
  499. return FAILED;
  500. }
  501. if((exit_status = setup_the_application(dz))<0) {
  502. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  503. return(FAILED);
  504. }
  505. if((exit_status = count_and_allocate_for_infiles(cmdlinecnt,cmdline,dz))<0) { // CDP LIB
  506. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  507. return(FAILED);
  508. }
  509. } else {
  510. //parse_TK_data() =
  511. if((exit_status = parse_sloom_data(argc,argv,&cmdline,&cmdlinecnt,dz))<0) {
  512. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  513. return(exit_status);
  514. }
  515. }
  516. // ap = dz->application;
  517. // parse_infile_and_hone_type() =
  518. if((exit_status = parse_infile_and_check_type(cmdline,dz))<0) {
  519. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  520. return(FAILED);
  521. }
  522. // setup_param_ranges_and_defaults() =
  523. if((exit_status = setup_the_param_ranges_and_defaults(dz))<0) {
  524. exit_status = print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  525. return(FAILED);
  526. }
  527. // open_first_infile CDP LIB
  528. if((exit_status = open_first_infile(cmdline[0],dz))<0) {
  529. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  530. return(FAILED);
  531. }
  532. cmdlinecnt--;
  533. cmdline++;
  534. // handle_outfile() =
  535. if((exit_status = handle_the_outfile(&cmdlinecnt,&cmdline,is_launched,dz))<0) {
  536. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  537. return(FAILED);
  538. }
  539. if(!sloom) {
  540. exit_status = CONTINUE;
  541. switch(dz->mode) {
  542. case(F_SEE): // fall thro
  543. case(F_SYLABTROF): // fall thro
  544. case(F_SEEPKS): break;
  545. case(F_NARROW): // fall thro
  546. case(F_ROTATE): // fall thro
  547. case(F_SUPPRESS): // fall thro
  548. case(F_ARPEG): // fall thro
  549. case(F_OCTSHIFT): // fall thro
  550. case(F_TRANS): // fall thro
  551. case(F_FRQSHIFT): // fall thro
  552. case(F_RESPACE): // fall thro
  553. case(F_PINVERT): // fall thro
  554. case(F_PQUANT): // fall thro
  555. case(F_RAND): // fall thro
  556. case(F_INVERT): if(cmdlinecnt < 1) exit_status = FAILED; break;
  557. case(F_PEXAGG): // fall thro
  558. case(F_SINUS): // fall thro
  559. case(F_MAKEFILT): // fall thro
  560. case(F_SQUEEZE): if(cmdlinecnt < 2) exit_status = FAILED; break;
  561. case(F_PCHRAND): if(cmdlinecnt < 3) exit_status = FAILED; break;
  562. case(F_MOVE2): // fall thro
  563. case(F_MOVE): if(cmdlinecnt < 4) exit_status = FAILED; break;
  564. case(F_NEGATE): break;
  565. default:
  566. fprintf(stderr,"Unknown mode (%d) at 3rd usage check.\n",dz->mode+1);
  567. return PROGRAM_ERROR;
  568. }
  569. if(exit_status == FAILED) {
  570. usage4(dz->mode);
  571. return FAILED;
  572. }
  573. }
  574. dz->retain_unpitched_data_for_deletion = 0;
  575. if(dz->mode == F_SINUS) {
  576. if((dz->iparray = (int **)malloc(IBIGARRAYCNT * sizeof(int*)))==NULL) {
  577. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY for stores of formant tracking data.\n");
  578. fflush(stdout);
  579. return(FAILED);
  580. }
  581. for(n=0;n<IBIGARRAYCNT;n++)
  582. dz->iparray[n] = NULL;
  583. } else {
  584. if((dz->iparray = (int **)malloc(IARRAYCNT * sizeof(int*)))==NULL) {
  585. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY for store of locations of peaks and troughs(1).\n");
  586. fflush(stdout);
  587. return(FAILED);
  588. }
  589. }
  590. if((dz->parray = (double **)malloc(TOT_DBLARRAYCNT * sizeof(double *)))==NULL) {
  591. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store Filter Data.\n");
  592. fflush(stdout);
  593. return(FAILED);
  594. }
  595. for(n=0;n<TOT_DBLARRAYCNT;n++)
  596. dz->parray[n] = NULL;
  597. if((dz->fptr = (float **)malloc(TOTAL_FLARRAYCNT * sizeof(float *)))==NULL) {
  598. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store Intermediate formant data.\n");
  599. fflush(stdout);
  600. return(FAILED);
  601. }
  602. for(n=0;n < TOTAL_FLARRAYCNT;n++)
  603. dz->fptr[n] = NULL;
  604. if((dz->lparray = (int **)malloc(TOTAL_LPARRAYCNT * sizeof(int *)))==NULL) {
  605. fprintf(stdout,"ERROR: INSUFFICIENT MEMORY to store Filter Times Data.(1)\n");
  606. fflush(stdout);
  607. return(FAILED);
  608. }
  609. // handle_formant_quiksearch() redundant
  610. // handle_special_data ....
  611. switch(dz->mode) {
  612. case(F_MAKEFILT):
  613. if((exit_status = handle_the_makefilt_special_data(cmdline[0],dz))<0) {
  614. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  615. return(FAILED);
  616. }
  617. cmdlinecnt--;
  618. cmdline++;
  619. break;
  620. case(F_PINVERT):
  621. if((exit_status = read_interval_mapping(cmdline[0],dz))<0) {
  622. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  623. return(FAILED);
  624. }
  625. cmdlinecnt--;
  626. cmdline++;
  627. break;
  628. case(F_PCHRAND): // fall thro
  629. case(F_PQUANT):
  630. if((exit_status = handle_the_pquantise_special_data(cmdline[0],dz))<0) {
  631. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  632. return(FAILED);
  633. }
  634. cmdlinecnt--;
  635. cmdline++;
  636. break;
  637. case(F_SINUS):
  638. if((exit_status = handle_the_pquantise_special_data(cmdline[0],dz))<0) {
  639. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  640. return(FAILED);
  641. }
  642. cmdlinecnt--;
  643. cmdline++;
  644. break;
  645. }
  646. if(!sloom && dz->mode == F_NARROW) {
  647. for(k = 0;k < cmdlinecnt;k++) {
  648. if(!strncmp(cmdline[k],"-s",2)) {
  649. if(strlen(cmdline[k]) > 2) {
  650. fprintf(stderr,"'-s' flag is for \"Use short windows\". Use '-o' for \"Suppress listed formants\".\n");
  651. return FAILED;
  652. }
  653. }
  654. }
  655. }
  656. if((exit_status = read_parameters_and_flags(&cmdline,&cmdlinecnt,dz))<0) { // CDP LIB
  657. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  658. return(FAILED);
  659. }
  660. //check_param_validity_and_consistency ....
  661. dz->fundamental = 0;
  662. dz->needpitch = 0;
  663. if((exit_status = check_specfnu_param_validity_and_consistency(dz))<0) {
  664. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  665. return(FAILED);
  666. }
  667. if((exit_status = exclude_non_harmonics(dz)) < 0) {
  668. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  669. return(FAILED);
  670. }
  671. if((exit_status = suppress_harmonics(dz)) < 0) {
  672. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  673. return(FAILED);
  674. }
  675. if(dz->xclude_nonh) { // To exclude non-harmonic components
  676. dz->fundamental = 1; // Need ot know the fundamental
  677. dz->needpitch = 1; // So need to do pitch-processing
  678. }
  679. if(dz->needpitch || dz->mode == F_SYLABTROF || dz->mode == F_SINUS) {
  680. if((exit_status = initialise_pitchwork(is_launched,dz))<0) {
  681. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  682. return(FAILED);
  683. }
  684. }
  685. // 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.
  686. if((exit_status = fwindow_size(dz))<0) {
  687. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  688. return(FAILED);
  689. }
  690. if(dz->shortwins)
  691. dz->formant_bands = SPECFNU_SHORT_FBANDS;
  692. else
  693. dz->formant_bands = SPECFNU_FBANDS;
  694. if(dz->mode == F_INVERT || dz->mode == F_NEGATE)
  695. contourcnt = 1;
  696. is_launched = TRUE;
  697. //allocate_large_buffers() ...
  698. dz->extra_bufcnt = 1;
  699. dz->bptrcnt = 4;
  700. if((exit_status = establish_spec_bufptrs_and_extra_buffers(dz))<0) {
  701. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  702. return(FAILED);
  703. }
  704. if((exit_status = setup_formant_arrays(&contourcnt,dz))<0) {
  705. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  706. return(FAILED);
  707. }
  708. if((dz->windowbuf[0] = (float *)malloc(dz->wanted * sizeof(float)))==NULL) {
  709. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonics markers.\n");
  710. return(MEMORY_ERROR);
  711. }
  712. if((exit_status = allocate_single_buffer(dz)) < 0) {
  713. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  714. return(FAILED);
  715. }
  716. dz->flbufptr[2] = dz->bigfbuf + dz->buflen; // End of buffer marker
  717. //param_preprocess ....
  718. if((exit_status = specfnu_preprocess(dz)) < 0) {
  719. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  720. return(FAILED);
  721. }
  722. //spec_process_file =
  723. if((exit_status = outer_specfnu_loop(contourcnt,dz)) < 0) {
  724. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  725. return(FAILED);
  726. }
  727. if((exit_status = complete_output(dz))<0) { // CDP LIB
  728. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  729. return(FAILED);
  730. }
  731. exit_status = print_messages_and_close_sndfiles(FINISHED,is_launched,dz); // CDP LIB
  732. free(dz);
  733. return(SUCCEEDED);
  734. }
  735. /**********************************************
  736. REPLACED CDP LIB FUNCTIONS
  737. **********************************************/
  738. /****************************** SET_PARAM_DATA *********************************/
  739. int set_param_data(aplptr ap, int special_data,int maxparamcnt,int paramcnt,char *paramlist)
  740. {
  741. ap->special_data = (char)special_data;
  742. ap->param_cnt = (char)paramcnt;
  743. ap->max_param_cnt = (char)maxparamcnt;
  744. if(ap->max_param_cnt>0) {
  745. if((ap->param_list = (char *)malloc((size_t)(ap->max_param_cnt+1)))==NULL) {
  746. sprintf(errstr,"INSUFFICIENT MEMORY: for param_list\n");
  747. return(MEMORY_ERROR);
  748. }
  749. strcpy(ap->param_list,paramlist);
  750. }
  751. return(FINISHED);
  752. }
  753. /****************************** SET_VFLGS *********************************/
  754. int set_vflgs
  755. (aplptr ap,char *optflags,int optcnt,char *optlist,char *varflags,int vflagcnt, int vparamcnt,char *varlist)
  756. {
  757. ap->option_cnt = (char) optcnt; /*RWD added cast */
  758. if(optcnt) {
  759. if((ap->option_list = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  760. sprintf(errstr,"INSUFFICIENT MEMORY: for option_list\n");
  761. return(MEMORY_ERROR);
  762. }
  763. strcpy(ap->option_list,optlist);
  764. if((ap->option_flags = (char *)malloc((size_t)(optcnt+1)))==NULL) {
  765. sprintf(errstr,"INSUFFICIENT MEMORY: for option_flags\n");
  766. return(MEMORY_ERROR);
  767. }
  768. strcpy(ap->option_flags,optflags);
  769. }
  770. ap->vflag_cnt = (char) vflagcnt;
  771. ap->variant_param_cnt = (char) vparamcnt;
  772. if(vflagcnt) {
  773. if((ap->variant_list = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  774. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_list\n");
  775. return(MEMORY_ERROR);
  776. }
  777. strcpy(ap->variant_list,varlist);
  778. if((ap->variant_flags = (char *)malloc((size_t)(vflagcnt+1)))==NULL) {
  779. sprintf(errstr,"INSUFFICIENT MEMORY: for variant_flags\n");
  780. return(MEMORY_ERROR);
  781. }
  782. strcpy(ap->variant_flags,varflags);
  783. }
  784. return(FINISHED);
  785. }
  786. /***************************** APPLICATION_INIT **************************/
  787. int application_init(dataptr dz)
  788. {
  789. int exit_status;
  790. int storage_cnt;
  791. int tipc, brkcnt;
  792. aplptr ap = dz->application;
  793. if(ap->vflag_cnt>0)
  794. initialise_vflags(dz);
  795. tipc = ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt;
  796. ap->total_input_param_cnt = (char)tipc;
  797. if(tipc>0) {
  798. if((exit_status = setup_input_param_range_stores(tipc,ap))<0)
  799. return(exit_status);
  800. if((exit_status = setup_input_param_defaultval_stores(tipc,ap))<0)
  801. return(exit_status);
  802. if((exit_status = setup_and_init_input_param_activity(dz,tipc))<0)
  803. return(exit_status);
  804. }
  805. brkcnt = tipc;
  806. if(brkcnt>0) {
  807. if((exit_status = setup_and_init_input_brktable_constants(dz,brkcnt))<0)
  808. return(exit_status);
  809. }
  810. if((storage_cnt = tipc + ap->internal_param_cnt)>0) {
  811. if((exit_status = setup_parameter_storage_and_constants(storage_cnt,dz))<0)
  812. return(exit_status);
  813. if((exit_status = initialise_is_int_and_no_brk_constants(storage_cnt,dz))<0)
  814. return(exit_status);
  815. }
  816. if((exit_status = mark_parameter_types(dz,ap))<0)
  817. return(exit_status);
  818. // establish_infile_constants() replaced by
  819. dz->infilecnt = ONE_NONSND_FILE;
  820. //establish_bufptrs_and_extra_buffers():
  821. return(FINISHED);
  822. }
  823. /******************************** SETUP_AND_INIT_INPUT_BRKTABLE_CONSTANTS ********************************/
  824. int setup_and_init_input_brktable_constants(dataptr dz,int brkcnt)
  825. {
  826. int n;
  827. if((dz->brk = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  828. sprintf(errstr,"setup_and_init_input_brktable_constants(): 1\n");
  829. return(MEMORY_ERROR);
  830. }
  831. if((dz->brkptr = (double **)malloc(brkcnt * sizeof(double *)))==NULL) {
  832. sprintf(errstr,"setup_and_init_input_brktable_constants(): 6\n");
  833. return(MEMORY_ERROR);
  834. }
  835. if((dz->brksize = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  836. sprintf(errstr,"setup_and_init_input_brktable_constants(): 2\n");
  837. return(MEMORY_ERROR);
  838. }
  839. if((dz->firstval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  840. sprintf(errstr,"setup_and_init_input_brktable_constants(): 3\n");
  841. return(MEMORY_ERROR);
  842. }
  843. if((dz->lastind = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  844. sprintf(errstr,"setup_and_init_input_brktable_constants(): 4\n");
  845. return(MEMORY_ERROR);
  846. }
  847. if((dz->lastval = (double *)malloc(brkcnt * sizeof(double)))==NULL) {
  848. sprintf(errstr,"setup_and_init_input_brktable_constants(): 5\n");
  849. return(MEMORY_ERROR);
  850. }
  851. if((dz->brkinit = (int *)malloc(brkcnt * sizeof(int)))==NULL) {
  852. sprintf(errstr,"setup_and_init_input_brktable_constants(): 7\n");
  853. return(MEMORY_ERROR);
  854. }
  855. for(n=0;n<brkcnt;n++) {
  856. dz->brk[n] = NULL;
  857. dz->brkptr[n] = NULL;
  858. dz->brkinit[n] = 0;
  859. dz->brksize[n] = 0;
  860. }
  861. return(FINISHED);
  862. }
  863. /********************** SETUP_PARAMETER_STORAGE_AND_CONSTANTS ********************/
  864. /* RWD mallo changed to calloc; helps debug verison run as release! */
  865. int setup_parameter_storage_and_constants(int storage_cnt,dataptr dz)
  866. {
  867. if((dz->param = (double *)calloc(storage_cnt, sizeof(double)))==NULL) {
  868. sprintf(errstr,"setup_parameter_storage_and_constants(): 1\n");
  869. return(MEMORY_ERROR);
  870. }
  871. if((dz->iparam = (int *)calloc(storage_cnt, sizeof(int) ))==NULL) {
  872. sprintf(errstr,"setup_parameter_storage_and_constants(): 2\n");
  873. return(MEMORY_ERROR);
  874. }
  875. if((dz->is_int = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  876. sprintf(errstr,"setup_parameter_storage_and_constants(): 3\n");
  877. return(MEMORY_ERROR);
  878. }
  879. if((dz->no_brk = (char *)calloc(storage_cnt, sizeof(char)))==NULL) {
  880. sprintf(errstr,"setup_parameter_storage_and_constants(): 5\n");
  881. return(MEMORY_ERROR);
  882. }
  883. return(FINISHED);
  884. }
  885. /************** INITIALISE_IS_INT_AND_NO_BRK_CONSTANTS *****************/
  886. int initialise_is_int_and_no_brk_constants(int storage_cnt,dataptr dz)
  887. {
  888. int n;
  889. for(n=0;n<storage_cnt;n++) {
  890. dz->is_int[n] = (char)0;
  891. dz->no_brk[n] = (char)0;
  892. }
  893. return(FINISHED);
  894. }
  895. /***************************** MARK_PARAMETER_TYPES **************************/
  896. int mark_parameter_types(dataptr dz,aplptr ap)
  897. {
  898. int n, m; /* PARAMS */
  899. for(n=0;n<ap->max_param_cnt;n++) {
  900. switch(ap->param_list[n]) {
  901. case('0'): break; /* dz->is_active[n] = 0 is default */
  902. case('i'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1;dz->no_brk[n] = (char)1; break;
  903. case('I'): dz->is_active[n] = (char)1; dz->is_int[n] = (char)1; break;
  904. case('d'): dz->is_active[n] = (char)1; dz->no_brk[n] = (char)1; break;
  905. case('D'): dz->is_active[n] = (char)1; /* normal case: double val or brkpnt file */ break;
  906. default:
  907. sprintf(errstr,"Programming error: invalid parameter type in mark_parameter_types()\n");
  908. return(PROGRAM_ERROR);
  909. }
  910. } /* OPTIONS */
  911. for(n=0,m=ap->max_param_cnt;n<ap->option_cnt;n++,m++) {
  912. switch(ap->option_list[n]) {
  913. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  914. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  915. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  916. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  917. default:
  918. sprintf(errstr,"Programming error: invalid option type in mark_parameter_types()\n");
  919. return(PROGRAM_ERROR);
  920. }
  921. } /* VARIANTS */
  922. for(n=0,m=ap->max_param_cnt + ap->option_cnt;n < ap->variant_param_cnt; n++, m++) {
  923. switch(ap->variant_list[n]) {
  924. case('0'): break;
  925. case('i'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  926. case('I'): dz->is_active[m] = (char)1; dz->is_int[m] = (char)1; break;
  927. case('d'): dz->is_active[m] = (char)1; dz->no_brk[m] = (char)1; break;
  928. case('D'): dz->is_active[m] = (char)1; /* normal case: double val or brkpnt file */ break;
  929. default:
  930. sprintf(errstr,"Programming error: invalid variant type in mark_parameter_types()\n");
  931. return(PROGRAM_ERROR);
  932. }
  933. } /* INTERNAL */
  934. for(n=0,
  935. m=ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt; n<ap->internal_param_cnt; n++,m++) {
  936. switch(ap->internal_param_list[n]) {
  937. case('0'): break; /* dummy variables: variables not used: but important for internal paream numbering!! */
  938. case('i'): dz->is_int[m] = (char)1; dz->no_brk[m] = (char)1; break;
  939. case('d'): dz->no_brk[m] = (char)1; break;
  940. default:
  941. sprintf(errstr,"Programming error: invalid internal param type in mark_parameter_types()\n");
  942. return(PROGRAM_ERROR);
  943. }
  944. }
  945. return(FINISHED);
  946. }
  947. /***************************** HANDLE_THE_OUTFILE **************************/
  948. int handle_the_outfile(int *cmdlinecnt,char ***cmdline,int is_launched,dataptr dz)
  949. {
  950. int exit_status, len, orig_chans = 1;
  951. char *filename = NULL;
  952. len = strlen((*cmdline)[0]);
  953. if((filename = (char *)malloc(len + 8))==NULL) {
  954. sprintf(errstr,"handle_the_outfile()\n");
  955. return(MEMORY_ERROR);
  956. }
  957. strcpy(filename,(*cmdline)[0]);
  958. //RWD this scuppers everyting at the command line, not least a pvx file extension
  959. if(sloom){
  960. if(dz->mode == F_SEEPKS || dz->mode == F_SYLABTROF || dz->mode == F_MAKEFILT)
  961. force_extension(1,filename);
  962. else
  963. force_extension(0,filename);
  964. }
  965. strcpy(dz->outfilename,filename);
  966. if(dz->mode == F_SEE) {
  967. orig_chans = dz->infile->channels;
  968. dz->infile->channels = 1;
  969. }
  970. if((exit_status = create_sized_outfile(filename,dz))<0)
  971. return(exit_status);
  972. if(dz->mode == F_SEE)
  973. dz->infile->channels = orig_chans;
  974. (*cmdline)++;
  975. (*cmdlinecnt)--;
  976. return(FINISHED);
  977. }
  978. /***************************** ESTABLISH_APPLICATION **************************/
  979. int establish_application(dataptr dz)
  980. {
  981. aplptr ap;
  982. if((dz->application = (aplptr)malloc(sizeof (struct applic)))==NULL) {
  983. sprintf(errstr,"establish_application()\n");
  984. return(MEMORY_ERROR);
  985. }
  986. ap = dz->application;
  987. memset((char *)ap,0,sizeof(struct applic));
  988. return(FINISHED);
  989. }
  990. /************************* INITIALISE_VFLAGS *************************/
  991. int initialise_vflags(dataptr dz)
  992. {
  993. int n;
  994. if((dz->vflag = (char *)malloc(dz->application->vflag_cnt * sizeof(char)))==NULL) {
  995. sprintf(errstr,"INSUFFICIENT MEMORY: vflag store,\n");
  996. return(MEMORY_ERROR);
  997. }
  998. for(n=0;n<dz->application->vflag_cnt;n++)
  999. dz->vflag[n] = FALSE;
  1000. return FINISHED;
  1001. }
  1002. /************************* SETUP_INPUT_PARAM_DEFAULTVALS *************************/
  1003. int setup_input_param_defaultval_stores(int tipc,aplptr ap)
  1004. {
  1005. int n;
  1006. if((ap->default_val = (double *)malloc(tipc * sizeof(double)))==NULL) {
  1007. sprintf(errstr,"INSUFFICIENT MEMORY for application default values store\n");
  1008. return(MEMORY_ERROR);
  1009. }
  1010. for(n=0;n<tipc;n++)
  1011. ap->default_val[n] = 0.0;
  1012. return(FINISHED);
  1013. }
  1014. /***************************** SETUP_AND_INIT_INPUT_PARAM_ACTIVITY **************************/
  1015. int setup_and_init_input_param_activity(dataptr dz,int tipc)
  1016. {
  1017. int n;
  1018. if((dz->is_active = (char *)malloc((size_t)tipc))==NULL) {
  1019. sprintf(errstr,"setup_and_init_input_param_activity()\n");
  1020. return(MEMORY_ERROR);
  1021. }
  1022. for(n=0;n<tipc;n++)
  1023. dz->is_active[n] = (char)0;
  1024. return(FINISHED);
  1025. }
  1026. /************************* SETUP_THE_APPLICATION *******************/
  1027. int setup_the_application(dataptr dz)
  1028. {
  1029. int exit_status;
  1030. aplptr ap;
  1031. if((exit_status = establish_application(dz))<0) // GLOBAL
  1032. return(FAILED);
  1033. ap = dz->application;
  1034. // SEE parstruct FOR EXPLANATION of next 2 functions
  1035. switch(dz->mode) {
  1036. // resynth modes
  1037. case(F_NARROW): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1038. case(F_SQUEEZE): exit_status = set_param_data(ap,0 ,2,2,"Di"); break;
  1039. case(F_INVERT): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1040. case(F_ROTATE): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1041. case(F_NEGATE): exit_status = set_param_data(ap,0 ,2,0,"00"); break;
  1042. case(F_SUPPRESS):exit_status = set_param_data(ap,0 ,2,1,"i0"); break;
  1043. // text-out mode
  1044. case(F_MAKEFILT):exit_status = set_param_data(ap,FFILT,2,1,"i0"); break;
  1045. // resynth modes
  1046. case(F_MOVE): exit_status = set_param_data(ap,0 ,4,4,"DDDD"); break;
  1047. case(F_MOVE2): exit_status = set_param_data(ap,0 ,4,4,"DDDD"); break;
  1048. case(F_ARPEG): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1049. case(F_OCTSHIFT):exit_status = set_param_data(ap,0 ,2,1,"I0"); break;
  1050. case(F_TRANS): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1051. case(F_FRQSHIFT):exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1052. case(F_RESPACE): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1053. case(F_PINVERT): exit_status = set_param_data(ap,INTERVAL_MAPPING,2,1,"D0"); break;
  1054. case(F_PEXAGG): exit_status = set_param_data(ap,0 ,2,2,"DD"); break;
  1055. case(F_PQUANT): exit_status = set_param_data(ap,HFIELD,2,0,"00"); break;
  1056. case(F_PCHRAND): exit_status = set_param_data(ap,HFIELD_OR_ZERO,2,2,"DD"); break;
  1057. case(F_RAND): exit_status = set_param_data(ap,0 ,2,1,"D0"); break;
  1058. // psuedosnd-out mode
  1059. case(F_SEE): break;
  1060. // text-out modes
  1061. case(F_SEEPKS): break;
  1062. case(F_SYLABTROF): break;
  1063. // resynth modes
  1064. case(F_SINUS): exit_status = set_param_data(ap,HFIELD_OR_ZERO,2,1,"D0"); break;
  1065. default:
  1066. fprintf(stderr,"Unknown mode at setup_the_application()\n");
  1067. return PROGRAM_ERROR;
  1068. }
  1069. if(exit_status < 0)
  1070. return(FAILED);
  1071. switch(dz->mode) {
  1072. // resynth modes
  1073. case(F_NARROW): exit_status = set_vflgs(ap,"go",2,"di","tfsxkr",6,0,"000000");break;
  1074. case(F_SQUEEZE): exit_status = set_vflgs(ap,"g", 1,"d", "tfsxkr",6,0,"000000");break;
  1075. case(F_INVERT): exit_status = set_vflgs(ap,"g", 1,"d", "sxkr", 4,0,"0000"); break;
  1076. case(F_ROTATE): exit_status = set_vflgs(ap,"g", 1,"d", "sxkr", 4,0,"0000"); break;
  1077. case(F_NEGATE): exit_status = set_vflgs(ap,"g", 1,"d", "f", 1,0,"0"); break;
  1078. case(F_SUPPRESS): exit_status = set_vflgs(ap,"g", 1,"d", "sx", 2,0,"00"); break;
  1079. // text-out modes
  1080. case(F_MAKEFILT): exit_status = set_vflgs(ap,"b", 1,"d", "kifs", 4,0,"0000"); break;
  1081. // resynth modes
  1082. case(F_MOVE): exit_status = set_vflgs(ap,"g", 1,"d", "tsxkr", 5,0,"00000"); break;
  1083. case(F_MOVE2): exit_status = set_vflgs(ap,"g", 1,"d", "tsnxkr",6,0,"000000");break;
  1084. case(F_ARPEG): exit_status = set_vflgs(ap,"g", 1,"d", "sxrdc", 5,0,"00000"); break;
  1085. case(F_OCTSHIFT): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1086. case(F_TRANS): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1087. case(F_FRQSHIFT): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1088. case(F_RESPACE): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdcf",6,0,"000000"); break;
  1089. case(F_PINVERT): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdc", 5,0,"00000"); break;
  1090. case(F_PEXAGG): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdcTFMAB",10,0,"000000000"); break;
  1091. case(F_PQUANT): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdcon", 7,0,"0000000"); break;
  1092. case(F_PCHRAND): exit_status = set_vflgs(ap,"glhpbt",6,"dddDdd","sxrdconk", 8,0,"00000000"); break;
  1093. case(F_RAND): exit_status = set_vflgs(ap,"glhp",4,"dddD","sxrdc", 5,0,"00000"); break;
  1094. // psuedosnd-out mode
  1095. case(F_SEE): exit_status = set_vflgs(ap,"", 0,"" , "s", 1,0,"0"); break;
  1096. // text-out modes
  1097. case(F_SEEPKS): exit_status = set_vflgs(ap,"", 0,"" , "s", 1,0,"0"); break;
  1098. case(F_SYLABTROF):exit_status = set_vflgs(ap,"sp",2,"dd","PB", 2,0,"00"); break;
  1099. // resynth modes
  1100. case(F_SINUS): exit_status = set_vflgs(ap,"abcdeqpon",9,"dDDDDDDDD","sfrS",4,0,"0000");break;
  1101. }
  1102. if(exit_status < 0)
  1103. return(FAILED);
  1104. dz->has_otherfile = FALSE;
  1105. dz->input_data_type = ANALFILE_ONLY;
  1106. switch(dz->mode) {
  1107. case(F_SEE):
  1108. dz->process_type = PSEUDOSNDFILE;
  1109. dz->outfiletype = SNDFILE_OUT;
  1110. break;
  1111. case(F_SEEPKS): // fall thro
  1112. case(F_SYLABTROF): // fall thro
  1113. case(F_MAKEFILT):
  1114. dz->process_type = TO_TEXTFILE;
  1115. dz->outfiletype = TEXTFILE_OUT;
  1116. break;
  1117. default:
  1118. dz->process_type = BIG_ANALFILE; // Add zero windowS at end, to avoid click
  1119. dz->outfiletype = ANALFILE_OUT;
  1120. }
  1121. return application_init(dz); //GLOBAL
  1122. }
  1123. /************************* PARSE_INFILE_AND_CHECK_TYPE *******************/
  1124. int parse_infile_and_check_type(char **cmdline,dataptr dz)
  1125. {
  1126. int exit_status;
  1127. infileptr infile_info;
  1128. if(!sloom) {
  1129. if((infile_info = (infileptr)malloc(sizeof(struct filedata)))==NULL) {
  1130. sprintf(errstr,"INSUFFICIENT MEMORY for infile structure to test file data.");
  1131. return(MEMORY_ERROR);
  1132. } else if((exit_status = cdparse(cmdline[0],infile_info))<0) {
  1133. sprintf(errstr,"Failed to parse input file %s\n",cmdline[0]);
  1134. return(PROGRAM_ERROR);
  1135. } else if(infile_info->filetype != ANALFILE) {
  1136. sprintf(errstr,"File %s is not of correct type\n",cmdline[0]);
  1137. return(DATA_ERROR);
  1138. } else if((exit_status = copy_parse_info_to_main_structure(infile_info,dz))<0) {
  1139. sprintf(errstr,"Failed to copy file parsing information\n");
  1140. return(PROGRAM_ERROR);
  1141. }
  1142. free(infile_info);
  1143. }
  1144. dz->clength = dz->wanted / 2;
  1145. dz->chwidth = dz->nyquist/(double)(dz->clength-1);
  1146. dz->halfchwidth = dz->chwidth/2.0;
  1147. return(FINISHED);
  1148. }
  1149. /************************* SETUP_THE_PARAM_RANGES_AND_DEFAULTS *******************/
  1150. int setup_the_param_ranges_and_defaults(dataptr dz)
  1151. {
  1152. int exit_status;
  1153. aplptr ap = dz->application;
  1154. // set_param_ranges()
  1155. ap->total_input_param_cnt = (char)(ap->max_param_cnt + ap->option_cnt + ap->variant_param_cnt);
  1156. // NB total_input_param_cnt is > 0 !!!s
  1157. if((exit_status = setup_input_param_range_stores(ap->total_input_param_cnt,ap))<0)
  1158. return(FAILED);
  1159. // get_param_ranges()
  1160. switch(dz->mode) {
  1161. case(F_NARROW):
  1162. ap->lo[NARROWING] = 1.0;
  1163. ap->hi[NARROWING] = 1000.0;
  1164. ap->default_val[NARROWING] = 2.0;
  1165. ap->lo[NARSUPRES] = 0;
  1166. ap->hi[NARSUPRES] = 234;
  1167. ap->default_val[NARSUPRES] = 0;
  1168. ap->lo[FGAIN] = 0.01;
  1169. ap->hi[FGAIN] = 10.0;
  1170. ap->default_val[FGAIN] = 1.0;
  1171. break;
  1172. case(F_SQUEEZE):
  1173. ap->lo[SQZFACT] = 1.0;
  1174. ap->hi[SQZFACT] = 10.0;
  1175. ap->default_val[SQZFACT] = 2.0;
  1176. ap->lo[SQZAT] = 1;
  1177. ap->hi[SQZAT] = 4;
  1178. ap->default_val[SQZAT] = 1;
  1179. ap->lo[FGAIN] = 0.01;
  1180. ap->hi[FGAIN] = 10.0;
  1181. ap->default_val[FGAIN] = 1.0;
  1182. break;
  1183. case(F_INVERT):
  1184. ap->lo[FVIB] = 0.0;
  1185. ap->hi[FVIB] = 300.0;
  1186. ap->default_val[FVIB] = 0.0;
  1187. ap->lo[FGAIN] = 0.01;
  1188. ap->hi[FGAIN] = 10.0;
  1189. ap->default_val[FGAIN] = 1.0;
  1190. break;
  1191. case(F_ROTATE):
  1192. ap->lo[RSPEED] = -300.0;
  1193. ap->hi[RSPEED] = 300.0;
  1194. ap->default_val[RSPEED] = 1.0;
  1195. ap->lo[FGAIN] = 0.01;
  1196. ap->hi[FGAIN] = 10.0;
  1197. ap->default_val[FGAIN] = 1.0;
  1198. break;
  1199. case(F_NEGATE):
  1200. ap->lo[FGAIN] = 0.01;
  1201. ap->hi[FGAIN] = 10.0;
  1202. ap->default_val[FGAIN] = 1.0;
  1203. break;
  1204. case(F_SUPPRESS):
  1205. ap->lo[SUPRF] = 1;
  1206. ap->hi[SUPRF] = 1234;
  1207. ap->default_val[SUPRF] = 1;
  1208. ap->lo[FGAIN] = 0.01;
  1209. ap->hi[FGAIN] = 10.0;
  1210. ap->default_val[FGAIN] = 1.0;
  1211. break;
  1212. case(F_MAKEFILT):
  1213. ap->lo[FPKCNT] = 1;
  1214. ap->hi[FPKCNT] = MAXFILTVALS;
  1215. ap->default_val[FPKCNT] = 1;
  1216. ap->lo[FBELOW] = 0;
  1217. ap->hi[FBELOW] = 127;
  1218. ap->default_val[FBELOW] = 0;
  1219. break;
  1220. case(F_MOVE):
  1221. ap->lo[FMOVE1] = -8000;
  1222. ap->hi[FMOVE1] = 8000.0;
  1223. ap->default_val[FMOVE1] = 0.0;
  1224. ap->lo[FMOVE2] = -8000;
  1225. ap->hi[FMOVE2] = 8000.0;
  1226. ap->default_val[FMOVE2] = 0.0;
  1227. ap->lo[FMOVE3] = -8000;
  1228. ap->hi[FMOVE3] = 8000.0;
  1229. ap->default_val[FMOVE3] = 0.0;
  1230. ap->lo[FMOVE4] = -8000;
  1231. ap->hi[FMOVE4] = 8000.0;
  1232. ap->default_val[FMOVE4] = 0.0;
  1233. ap->lo[FMVGAIN] = 0.01;
  1234. ap->hi[FMVGAIN] = 10.0;
  1235. ap->default_val[FMVGAIN] = 1.0;
  1236. break;
  1237. case(F_MOVE2):
  1238. ap->lo[FMOVE1] = 10;
  1239. ap->hi[FMOVE1] = 8000.0;
  1240. ap->default_val[FMOVE1] = 200;
  1241. ap->lo[FMOVE2] = 10;
  1242. ap->hi[FMOVE2] = 8000.0;
  1243. ap->default_val[FMOVE2] = 1200;
  1244. ap->lo[FMOVE3] = 10;
  1245. ap->hi[FMOVE3] = 8000.0;
  1246. ap->default_val[FMOVE3] = 2000;
  1247. ap->lo[FMOVE4] = 10;
  1248. ap->hi[FMOVE4] = 8000.0;
  1249. ap->default_val[FMOVE4] = 3200;
  1250. ap->lo[FMVGAIN] = 0.01;
  1251. ap->hi[FMVGAIN] = 10.0;
  1252. ap->default_val[FMVGAIN] = 1.0;
  1253. break;
  1254. case(F_SYLABTROF):
  1255. ap->lo[FMINSYL] = .05;
  1256. ap->hi[FMINSYL] = .5;
  1257. ap->default_val[FMINSYL] = MIN_SYLLAB_DUR; // 0.08
  1258. ap->lo[FMINPKG] = 0.01;
  1259. ap->hi[FMINPKG] = 0.2;
  1260. ap->default_val[FMINPKG] = MIN_PEAKTROF_GAP; // 0.08
  1261. break;
  1262. case(F_ARPEG):
  1263. ap->lo[FARPRATE] = -50.0;
  1264. ap->hi[FARPRATE] = 50.0;
  1265. ap->default_val[FARPRATE] = 1.0;
  1266. ap->lo[FGAIN] = 0.01;
  1267. ap->hi[FGAIN] = 10.0;
  1268. ap->default_val[FGAIN] = 1.0;
  1269. break;
  1270. case(F_OCTSHIFT):
  1271. ap->lo[COLINT] = -4.0;
  1272. ap->hi[COLINT] = 4.0;
  1273. ap->default_val[COLINT] = 1.0;
  1274. ap->lo[FGAIN] = 0.01;
  1275. ap->hi[FGAIN] = 10.0;
  1276. ap->default_val[FGAIN] = 1.0;
  1277. ap->lo[COL_LO] = 0.0;
  1278. ap->hi[COL_LO] = 10000.0;
  1279. ap->default_val[COL_LO] = 0.0;
  1280. ap->lo[COL_HI] = 50.0;
  1281. ap->hi[COL_HI] = 10000.0;
  1282. ap->default_val[COL_HI] = 2000.0;
  1283. ap->lo[COLRATE] = -50.0;
  1284. ap->hi[COLRATE] = 50.0;
  1285. ap->default_val[COLRATE] = 0.0;
  1286. break;
  1287. case(F_TRANS):
  1288. ap->lo[COLFLT] = -48.0;
  1289. ap->hi[COLFLT] = 48.0;
  1290. ap->default_val[COLFLT] = 1.0;
  1291. ap->lo[FGAIN] = 0.01;
  1292. ap->hi[FGAIN] = 10.0;
  1293. ap->default_val[FGAIN] = 1.0;
  1294. ap->lo[COL_LO] = 0.0;
  1295. ap->hi[COL_LO] = 10000.0;
  1296. ap->default_val[COL_LO] = 0.0;
  1297. ap->lo[COL_HI] = 50.0;
  1298. ap->hi[COL_HI] = 10000.0;
  1299. ap->default_val[COL_HI] = 2000.0;
  1300. ap->lo[COLRATE] = -50.0;
  1301. ap->hi[COLRATE] = 50.0;
  1302. ap->default_val[COLRATE] = 0.0;
  1303. break;
  1304. case(F_FRQSHIFT):
  1305. ap->lo[COLFLT] = -1000.0;
  1306. ap->hi[COLFLT] = 1000.0;
  1307. ap->default_val[COLFLT] = 100.0;
  1308. ap->lo[FGAIN] = 0.01;
  1309. ap->hi[FGAIN] = 10.0;
  1310. ap->default_val[FGAIN] = 1.0;
  1311. ap->lo[COL_LO] = 0.0;
  1312. ap->hi[COL_LO] = 10000.0;
  1313. ap->default_val[COL_LO] = 0.0;
  1314. ap->lo[COL_HI] = 50.0;
  1315. ap->hi[COL_HI] = 10000.0;
  1316. ap->default_val[COL_HI] = 2000.0;
  1317. ap->lo[COLRATE] = -50.0;
  1318. ap->hi[COLRATE] = 50.0;
  1319. ap->default_val[COLRATE] = 0.0;
  1320. break;
  1321. case(F_RESPACE):
  1322. ap->lo[COLFLT] = 1.0;
  1323. ap->hi[COLFLT] = 1000.0;
  1324. ap->default_val[COLFLT] = 10.0;
  1325. ap->lo[FGAIN] = 0.01;
  1326. ap->hi[FGAIN] = 10.0;
  1327. ap->default_val[FGAIN] = 1.0;
  1328. ap->lo[COL_LO] = 0.0;
  1329. ap->hi[COL_LO] = 10000.0;
  1330. ap->default_val[COL_LO] = 0.0;
  1331. ap->lo[COL_HI] = 50.0;
  1332. ap->hi[COL_HI] = 10000.0;
  1333. ap->default_val[COL_HI] = 2000.0;
  1334. ap->lo[COLRATE] = -50.0;
  1335. ap->hi[COLRATE] = 50.0;
  1336. ap->default_val[COLRATE] = .0;
  1337. break;
  1338. case(F_PINVERT):
  1339. ap->lo[COLFLT] = 0.0;
  1340. ap->hi[COLFLT] = 127;
  1341. ap->default_val[COLFLT] = 60;
  1342. ap->lo[FGAIN] = 0.01;
  1343. ap->hi[FGAIN] = 10.0;
  1344. ap->default_val[FGAIN] = 1.0;
  1345. ap->lo[COL_LO] = 0.0;
  1346. ap->hi[COL_LO] = 10000.0;
  1347. ap->default_val[COL_LO] = 0.0;
  1348. ap->lo[COL_HI] = 50.0;
  1349. ap->hi[COL_HI] = 10000.0;
  1350. ap->default_val[COL_HI] = 2000.0;
  1351. ap->lo[COLRATE] = -50.0;
  1352. ap->hi[COLRATE] = 50.0;
  1353. ap->default_val[COLRATE] = 0.0;
  1354. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1355. ap->hi[COLLOPCH] = MIDIMAX;
  1356. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1357. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1358. ap->hi[COLHIPCH] = MIDIMAX;
  1359. ap->default_val[COLHIPCH] = MIDIMAX;
  1360. break;
  1361. case(F_PEXAGG):
  1362. ap->lo[COLFLT] = 0.0;
  1363. ap->hi[COLFLT] = MIDIMAX;
  1364. ap->default_val[COLFLT] = 60;
  1365. ap->lo[EXAGRANG] = 0.0;
  1366. ap->hi[EXAGRANG] = PEX_MAX_RANG;
  1367. ap->default_val[EXAGRANG] = 1.0;
  1368. ap->lo[FGAIN] = 0.01;
  1369. ap->hi[FGAIN] = 10.0;
  1370. ap->default_val[FGAIN] = 1.0;
  1371. ap->lo[COL_LO] = 0.0;
  1372. ap->hi[COL_LO] = 10000.0;
  1373. ap->default_val[COL_LO] = 0.0;
  1374. ap->lo[COL_HI] = 50.0;
  1375. ap->hi[COL_HI] = 10000.0;
  1376. ap->default_val[COL_HI] = 2000.0;
  1377. ap->lo[COLRATE] = -50.0;
  1378. ap->hi[COLRATE] = 50.0;
  1379. ap->default_val[COLRATE] = 0.0;
  1380. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1381. ap->hi[COLLOPCH] = MIDIMAX;
  1382. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1383. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1384. ap->hi[COLHIPCH] = MIDIMAX;
  1385. ap->default_val[COLHIPCH] = MIDIMAX;
  1386. break;
  1387. case(F_PQUANT):
  1388. ap->lo[FGAIN] = 0.01;
  1389. ap->hi[FGAIN] = 10.0;
  1390. ap->default_val[FGAIN] = 1.0;
  1391. ap->lo[COL_LO] = 0.0;
  1392. ap->hi[COL_LO] = 10000.0;
  1393. ap->default_val[COL_LO] = 0.0;
  1394. ap->lo[COL_HI] = 50.0;
  1395. ap->hi[COL_HI] = 10000.0;
  1396. ap->default_val[COL_HI] = 2000.0;
  1397. ap->lo[COLRATE] = -50.0;
  1398. ap->hi[COLRATE] = 50.0;
  1399. ap->default_val[COLRATE] = 0.0;
  1400. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1401. ap->hi[COLLOPCH] = MIDIMAX;
  1402. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1403. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1404. ap->hi[COLHIPCH] = MIDIMAX;
  1405. ap->default_val[COLHIPCH] = MIDIMAX;
  1406. break;
  1407. case(F_PCHRAND):
  1408. ap->lo[FPRMAXINT] = 0.0;
  1409. ap->hi[FPRMAXINT] = RANDPITCHMAX;
  1410. ap->default_val[FPRMAXINT] = 2.0;
  1411. ap->lo[FSLEW] = 0.1;
  1412. ap->hi[FSLEW] = 10.0;
  1413. ap->default_val[FSLEW] = 1.0;
  1414. ap->lo[FGAIN] = 0.01;
  1415. ap->hi[FGAIN] = 10.0;
  1416. ap->default_val[FGAIN] = 1.0;
  1417. ap->lo[COL_LO] = 0.0;
  1418. ap->hi[COL_LO] = 10000.0;
  1419. ap->default_val[COL_LO] = 0.0;
  1420. ap->lo[COL_HI] = 50.0;
  1421. ap->hi[COL_HI] = 10000.0;
  1422. ap->default_val[COL_HI] = 2000.0;
  1423. ap->lo[COLRATE] = -50.0;
  1424. ap->hi[COLRATE] = 50.0;
  1425. ap->default_val[COLRATE] = 0.0;
  1426. ap->lo[COLLOPCH] = SPEC_MIDIMIN;
  1427. ap->hi[COLLOPCH] = MIDIMAX;
  1428. ap->default_val[COLLOPCH] = SPEC_MIDIMIN;
  1429. ap->lo[COLHIPCH] = SPEC_MIDIMIN;
  1430. ap->hi[COLHIPCH] = MIDIMAX;
  1431. ap->default_val[COLHIPCH] = MIDIMAX;
  1432. break;
  1433. case(F_RAND):
  1434. ap->lo[COLFLT] = 0.0;
  1435. ap->hi[COLFLT] = 1.0;
  1436. ap->default_val[COLFLT] = 0.1;
  1437. ap->lo[FGAIN] = 0.01;
  1438. ap->hi[FGAIN] = 10.0;
  1439. ap->default_val[FGAIN] = 1.0;
  1440. ap->lo[COL_LO] = 0.0;
  1441. ap->hi[COL_LO] = 10000.0;
  1442. ap->default_val[COL_LO] = 0.0;
  1443. ap->lo[COL_HI] = 50.0;
  1444. ap->hi[COL_HI] = 10000.0;
  1445. ap->default_val[COL_HI] = 2000.0;
  1446. ap->lo[COLRATE] = -50.0;
  1447. ap->hi[COLRATE] = 50.0;
  1448. ap->default_val[COLRATE] = 0.0;
  1449. break;
  1450. case(F_SINUS):
  1451. ap->lo[F_SINING] = 0.0;
  1452. ap->hi[F_SINING] = 1.0;
  1453. ap->default_val[F_SINING] = 1.0;
  1454. ap->lo[FGAIN] = 0.01;
  1455. ap->hi[FGAIN] = 10.0;
  1456. ap->default_val[FGAIN] = 1.0;
  1457. ap->lo[F_AMP1] = 0.0;
  1458. ap->hi[F_AMP1] = 10.0;
  1459. ap->default_val[F_AMP1] = 1.0;
  1460. ap->lo[F_AMP2] = 0.0;
  1461. ap->hi[F_AMP2] = 10.0;
  1462. ap->default_val[F_AMP2] = 1.0;
  1463. ap->lo[F_AMP3] = 0.0;
  1464. ap->hi[F_AMP3] = 10.0;
  1465. ap->default_val[F_AMP3] = 1.0;
  1466. ap->lo[F_AMP4] = 0.0;
  1467. ap->hi[F_AMP4] = 10.0;
  1468. ap->default_val[F_AMP4] = 1.0;
  1469. ap->lo[F_QDEP1] = 0.0;
  1470. ap->hi[F_QDEP1] = 1.0;
  1471. ap->default_val[F_QDEP1] = 0.0;
  1472. ap->lo[F_QDEP2] = 0.0;
  1473. ap->hi[F_QDEP2] = 1.0;
  1474. ap->default_val[F_QDEP2] = 0.0;
  1475. ap->lo[F_QDEP3] = 0.0;
  1476. ap->hi[F_QDEP3] = 1.0;
  1477. ap->default_val[F_QDEP3] = 0.0;
  1478. ap->lo[F_QDEP4] = 0.0;
  1479. ap->hi[F_QDEP4] = 1.0;
  1480. ap->default_val[F_QDEP4] = 0.0;
  1481. break;
  1482. }
  1483. dz->maxmode = 23;
  1484. if(!sloom)
  1485. put_default_vals_in_all_params(dz);
  1486. return(FINISHED);
  1487. }
  1488. /********************************* PARSE_SLOOM_DATA *********************************/
  1489. int parse_sloom_data(int argc,char *argv[],char ***cmdline,int *cmdlinecnt,dataptr dz)
  1490. {
  1491. int exit_status;
  1492. int cnt = 1, infilecnt;
  1493. int filesize, insams, inbrksize;
  1494. double dummy;
  1495. int true_cnt = 0;
  1496. // aplptr ap;
  1497. while(cnt<=PRE_CMDLINE_DATACNT) {
  1498. if(cnt > argc) {
  1499. sprintf(errstr,"Insufficient data sent from TK\n");
  1500. return(DATA_ERROR);
  1501. }
  1502. switch(cnt) {
  1503. case(1):
  1504. if(sscanf(argv[cnt],"%d",&dz->process)!=1) {
  1505. sprintf(errstr,"Cannot read process no. sent from TK\n");
  1506. return(DATA_ERROR);
  1507. }
  1508. break;
  1509. case(2):
  1510. if(sscanf(argv[cnt],"%d",&dz->mode)!=1) {
  1511. sprintf(errstr,"Cannot read mode no. sent from TK\n");
  1512. return(DATA_ERROR);
  1513. }
  1514. if(dz->mode > 0)
  1515. dz->mode--;
  1516. //setup_particular_application() =
  1517. if((exit_status = setup_the_application(dz))<0)
  1518. return(exit_status);
  1519. // ap = dz->application;
  1520. break;
  1521. case(3):
  1522. if(sscanf(argv[cnt],"%d",&infilecnt)!=1) {
  1523. sprintf(errstr,"Cannot read infilecnt sent from TK\n");
  1524. return(DATA_ERROR);
  1525. }
  1526. if(infilecnt < 1) {
  1527. true_cnt = cnt + 1;
  1528. cnt = PRE_CMDLINE_DATACNT; /* force exit from loop after assign_file_data_storage */
  1529. }
  1530. if((exit_status = assign_file_data_storage(infilecnt,dz))<0)
  1531. return(exit_status);
  1532. break;
  1533. case(INPUT_FILETYPE+4):
  1534. if(sscanf(argv[cnt],"%d",&dz->infile->filetype)!=1) {
  1535. sprintf(errstr,"Cannot read filetype sent from TK (%s)\n",argv[cnt]);
  1536. return(DATA_ERROR);
  1537. }
  1538. break;
  1539. case(INPUT_FILESIZE+4):
  1540. if(sscanf(argv[cnt],"%d",&filesize)!=1) {
  1541. sprintf(errstr,"Cannot read infilesize sent from TK\n");
  1542. return(DATA_ERROR);
  1543. }
  1544. dz->insams[0] = filesize;
  1545. break;
  1546. case(INPUT_INSAMS+4):
  1547. if(sscanf(argv[cnt],"%d",&insams)!=1) {
  1548. sprintf(errstr,"Cannot read insams sent from TK\n");
  1549. return(DATA_ERROR);
  1550. }
  1551. dz->insams[0] = insams;
  1552. break;
  1553. case(INPUT_SRATE+4):
  1554. if(sscanf(argv[cnt],"%d",&dz->infile->srate)!=1) {
  1555. sprintf(errstr,"Cannot read srate sent from TK\n");
  1556. return(DATA_ERROR);
  1557. }
  1558. break;
  1559. case(INPUT_CHANNELS+4):
  1560. if(sscanf(argv[cnt],"%d",&dz->infile->channels)!=1) {
  1561. sprintf(errstr,"Cannot read channels sent from TK\n");
  1562. return(DATA_ERROR);
  1563. }
  1564. break;
  1565. case(INPUT_STYPE+4):
  1566. if(sscanf(argv[cnt],"%d",&dz->infile->stype)!=1) {
  1567. sprintf(errstr,"Cannot read stype sent from TK\n");
  1568. return(DATA_ERROR);
  1569. }
  1570. break;
  1571. case(INPUT_ORIGSTYPE+4):
  1572. if(sscanf(argv[cnt],"%d",&dz->infile->origstype)!=1) {
  1573. sprintf(errstr,"Cannot read origstype sent from TK\n");
  1574. return(DATA_ERROR);
  1575. }
  1576. break;
  1577. case(INPUT_ORIGRATE+4):
  1578. if(sscanf(argv[cnt],"%d",&dz->infile->origrate)!=1) {
  1579. sprintf(errstr,"Cannot read origrate sent from TK\n");
  1580. return(DATA_ERROR);
  1581. }
  1582. break;
  1583. case(INPUT_MLEN+4):
  1584. if(sscanf(argv[cnt],"%d",&dz->infile->Mlen)!=1) {
  1585. sprintf(errstr,"Cannot read Mlen sent from TK\n");
  1586. return(DATA_ERROR);
  1587. }
  1588. break;
  1589. case(INPUT_DFAC+4):
  1590. if(sscanf(argv[cnt],"%d",&dz->infile->Dfac)!=1) {
  1591. sprintf(errstr,"Cannot read Dfac sent from TK\n");
  1592. return(DATA_ERROR);
  1593. }
  1594. break;
  1595. case(INPUT_ORIGCHANS+4):
  1596. if(sscanf(argv[cnt],"%d",&dz->infile->origchans)!=1) {
  1597. sprintf(errstr,"Cannot read origchans sent from TK\n");
  1598. return(DATA_ERROR);
  1599. }
  1600. break;
  1601. case(INPUT_SPECENVCNT+4):
  1602. if(sscanf(argv[cnt],"%d",&dz->infile->specenvcnt)!=1) {
  1603. sprintf(errstr,"Cannot read specenvcnt sent from TK\n");
  1604. return(DATA_ERROR);
  1605. }
  1606. dz->specenvcnt = dz->infile->specenvcnt;
  1607. break;
  1608. case(INPUT_WANTED+4):
  1609. if(sscanf(argv[cnt],"%d",&dz->wanted)!=1) {
  1610. sprintf(errstr,"Cannot read wanted sent from TK\n");
  1611. return(DATA_ERROR);
  1612. }
  1613. break;
  1614. case(INPUT_WLENGTH+4):
  1615. if(sscanf(argv[cnt],"%d",&dz->wlength)!=1) {
  1616. sprintf(errstr,"Cannot read wlength sent from TK\n");
  1617. return(DATA_ERROR);
  1618. }
  1619. break;
  1620. case(INPUT_OUT_CHANS+4):
  1621. if(sscanf(argv[cnt],"%d",&dz->out_chans)!=1) {
  1622. sprintf(errstr,"Cannot read out_chans sent from TK\n");
  1623. return(DATA_ERROR);
  1624. }
  1625. break;
  1626. /* RWD these chanegs to samps - tk will have to deal with that! */
  1627. case(INPUT_DESCRIPTOR_BYTES+4):
  1628. if(sscanf(argv[cnt],"%d",&dz->descriptor_samps)!=1) {
  1629. sprintf(errstr,"Cannot read descriptor_samps sent from TK\n");
  1630. return(DATA_ERROR);
  1631. }
  1632. break;
  1633. case(INPUT_IS_TRANSPOS+4):
  1634. if(sscanf(argv[cnt],"%d",&dz->is_transpos)!=1) {
  1635. sprintf(errstr,"Cannot read is_transpos sent from TK\n");
  1636. return(DATA_ERROR);
  1637. }
  1638. break;
  1639. case(INPUT_COULD_BE_TRANSPOS+4):
  1640. if(sscanf(argv[cnt],"%d",&dz->could_be_transpos)!=1) {
  1641. sprintf(errstr,"Cannot read could_be_transpos sent from TK\n");
  1642. return(DATA_ERROR);
  1643. }
  1644. break;
  1645. case(INPUT_COULD_BE_PITCH+4):
  1646. if(sscanf(argv[cnt],"%d",&dz->could_be_pitch)!=1) {
  1647. sprintf(errstr,"Cannot read could_be_pitch sent from TK\n");
  1648. return(DATA_ERROR);
  1649. }
  1650. break;
  1651. case(INPUT_DIFFERENT_SRATES+4):
  1652. if(sscanf(argv[cnt],"%d",&dz->different_srates)!=1) {
  1653. sprintf(errstr,"Cannot read different_srates sent from TK\n");
  1654. return(DATA_ERROR);
  1655. }
  1656. break;
  1657. case(INPUT_DUPLICATE_SNDS+4):
  1658. if(sscanf(argv[cnt],"%d",&dz->duplicate_snds)!=1) {
  1659. sprintf(errstr,"Cannot read duplicate_snds sent from TK\n");
  1660. return(DATA_ERROR);
  1661. }
  1662. break;
  1663. case(INPUT_BRKSIZE+4):
  1664. if(sscanf(argv[cnt],"%d",&inbrksize)!=1) {
  1665. sprintf(errstr,"Cannot read brksize sent from TK\n");
  1666. return(DATA_ERROR);
  1667. }
  1668. if(inbrksize > 0) {
  1669. switch(dz->input_data_type) {
  1670. case(WORDLIST_ONLY):
  1671. break;
  1672. case(PITCH_AND_PITCH):
  1673. case(PITCH_AND_TRANSPOS):
  1674. case(TRANSPOS_AND_TRANSPOS):
  1675. dz->tempsize = inbrksize;
  1676. break;
  1677. case(BRKFILES_ONLY):
  1678. case(UNRANGED_BRKFILE_ONLY):
  1679. case(DB_BRKFILES_ONLY):
  1680. case(ALL_FILES):
  1681. case(ANY_NUMBER_OF_ANY_FILES):
  1682. if(dz->extrabrkno < 0) {
  1683. sprintf(errstr,"Storage location number for brktable not established by CDP.\n");
  1684. return(DATA_ERROR);
  1685. }
  1686. if(dz->brksize == NULL) {
  1687. sprintf(errstr,"CDP has not established storage space for input brktable.\n");
  1688. return(PROGRAM_ERROR);
  1689. }
  1690. dz->brksize[dz->extrabrkno] = inbrksize;
  1691. break;
  1692. default:
  1693. sprintf(errstr,"TK sent brktablesize > 0 for input_data_type [%d] not using brktables.\n",
  1694. dz->input_data_type);
  1695. return(PROGRAM_ERROR);
  1696. }
  1697. break;
  1698. }
  1699. break;
  1700. case(INPUT_NUMSIZE+4):
  1701. if(sscanf(argv[cnt],"%d",&dz->numsize)!=1) {
  1702. sprintf(errstr,"Cannot read numsize sent from TK\n");
  1703. return(DATA_ERROR);
  1704. }
  1705. break;
  1706. case(INPUT_LINECNT+4):
  1707. if(sscanf(argv[cnt],"%d",&dz->linecnt)!=1) {
  1708. sprintf(errstr,"Cannot read linecnt sent from TK\n");
  1709. return(DATA_ERROR);
  1710. }
  1711. break;
  1712. case(INPUT_ALL_WORDS+4):
  1713. if(sscanf(argv[cnt],"%d",&dz->all_words)!=1) {
  1714. sprintf(errstr,"Cannot read all_words sent from TK\n");
  1715. return(DATA_ERROR);
  1716. }
  1717. break;
  1718. case(INPUT_ARATE+4):
  1719. if(sscanf(argv[cnt],"%f",&dz->infile->arate)!=1) {
  1720. sprintf(errstr,"Cannot read arate sent from TK\n");
  1721. return(DATA_ERROR);
  1722. }
  1723. break;
  1724. case(INPUT_FRAMETIME+4):
  1725. if(sscanf(argv[cnt],"%lf",&dummy)!=1) {
  1726. sprintf(errstr,"Cannot read frametime sent from TK\n");
  1727. return(DATA_ERROR);
  1728. }
  1729. dz->frametime = (float)dummy;
  1730. break;
  1731. case(INPUT_WINDOW_SIZE+4):
  1732. if(sscanf(argv[cnt],"%f",&dz->infile->window_size)!=1) {
  1733. sprintf(errstr,"Cannot read window_size sent from TK\n");
  1734. return(DATA_ERROR);
  1735. }
  1736. break;
  1737. case(INPUT_NYQUIST+4):
  1738. if(sscanf(argv[cnt],"%lf",&dz->nyquist)!=1) {
  1739. sprintf(errstr,"Cannot read nyquist sent from TK\n");
  1740. return(DATA_ERROR);
  1741. }
  1742. break;
  1743. case(INPUT_DURATION+4):
  1744. if(sscanf(argv[cnt],"%lf",&dz->duration)!=1) {
  1745. sprintf(errstr,"Cannot read duration sent from TK\n");
  1746. return(DATA_ERROR);
  1747. }
  1748. break;
  1749. case(INPUT_MINBRK+4):
  1750. if(sscanf(argv[cnt],"%lf",&dz->minbrk)!=1) {
  1751. sprintf(errstr,"Cannot read minbrk sent from TK\n");
  1752. return(DATA_ERROR);
  1753. }
  1754. break;
  1755. case(INPUT_MAXBRK+4):
  1756. if(sscanf(argv[cnt],"%lf",&dz->maxbrk)!=1) {
  1757. sprintf(errstr,"Cannot read maxbrk sent from TK\n");
  1758. return(DATA_ERROR);
  1759. }
  1760. break;
  1761. case(INPUT_MINNUM+4):
  1762. if(sscanf(argv[cnt],"%lf",&dz->minnum)!=1) {
  1763. sprintf(errstr,"Cannot read minnum sent from TK\n");
  1764. return(DATA_ERROR);
  1765. }
  1766. break;
  1767. case(INPUT_MAXNUM+4):
  1768. if(sscanf(argv[cnt],"%lf",&dz->maxnum)!=1) {
  1769. sprintf(errstr,"Cannot read maxnum sent from TK\n");
  1770. return(DATA_ERROR);
  1771. }
  1772. break;
  1773. default:
  1774. sprintf(errstr,"case switch item missing: parse_sloom_data()\n");
  1775. return(PROGRAM_ERROR);
  1776. }
  1777. cnt++;
  1778. }
  1779. if(cnt!=PRE_CMDLINE_DATACNT+1) {
  1780. sprintf(errstr,"Insufficient pre-cmdline params sent from TK\n");
  1781. return(DATA_ERROR);
  1782. }
  1783. if(true_cnt)
  1784. cnt = true_cnt;
  1785. *cmdlinecnt = 0;
  1786. while(cnt < argc) {
  1787. if((exit_status = get_tk_cmdline_word(cmdlinecnt,cmdline,argv[cnt]))<0)
  1788. return(exit_status);
  1789. cnt++;
  1790. }
  1791. return(FINISHED);
  1792. }
  1793. /********************************* GET_TK_CMDLINE_WORD *********************************/
  1794. int get_tk_cmdline_word(int *cmdlinecnt,char ***cmdline,char *q)
  1795. {
  1796. if(*cmdlinecnt==0) {
  1797. if((*cmdline = (char **)malloc(sizeof(char *)))==NULL) {
  1798. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1799. return(MEMORY_ERROR);
  1800. }
  1801. } else {
  1802. if((*cmdline = (char **)realloc(*cmdline,((*cmdlinecnt)+1) * sizeof(char *)))==NULL) {
  1803. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline array.\n");
  1804. return(MEMORY_ERROR);
  1805. }
  1806. }
  1807. if(((*cmdline)[*cmdlinecnt] = (char *)malloc((strlen(q) + 1) * sizeof(char)))==NULL) {
  1808. sprintf(errstr,"INSUFFICIENT MEMORY for TK cmdline item %d.\n",(*cmdlinecnt)+1);
  1809. return(MEMORY_ERROR);
  1810. }
  1811. strcpy((*cmdline)[*cmdlinecnt],q);
  1812. (*cmdlinecnt)++;
  1813. return(FINISHED);
  1814. }
  1815. /****************************** ASSIGN_FILE_DATA_STORAGE *********************************/
  1816. int assign_file_data_storage(int infilecnt,dataptr dz)
  1817. {
  1818. int exit_status;
  1819. int no_sndfile_system_files = FALSE;
  1820. dz->infilecnt = infilecnt;
  1821. if((exit_status = allocate_filespace(dz))<0)
  1822. return(exit_status);
  1823. if(no_sndfile_system_files)
  1824. dz->infilecnt = 0;
  1825. return(FINISHED);
  1826. }
  1827. /************************* redundant functions: to ensure libs compile OK *******************/
  1828. int assign_process_logic(dataptr dz)
  1829. {
  1830. return(FINISHED);
  1831. }
  1832. void set_legal_infile_structure(dataptr dz)
  1833. {}
  1834. int set_legal_internalparam_structure(int process,int mode,aplptr ap)
  1835. {
  1836. return(FINISHED);
  1837. }
  1838. int setup_internal_arrays_and_array_pointers(dataptr dz)
  1839. {
  1840. return(FINISHED);
  1841. }
  1842. int establish_bufptrs_and_extra_buffers(dataptr dz)
  1843. {
  1844. return(FINISHED);
  1845. }
  1846. int get_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1847. {
  1848. return(FINISHED);
  1849. }
  1850. int read_special_data(char *str,dataptr dz)
  1851. {
  1852. return(FINISHED);
  1853. }
  1854. int inner_loop
  1855. (int *peakscore,int *descnt,int *in_start_portion,int *least,int *pitchcnt,int windows_in_buf,dataptr dz)
  1856. {
  1857. return(FINISHED);
  1858. }
  1859. /********************************************************************************************/
  1860. int get_the_process_no(char *prog_identifier_from_cmdline,dataptr dz)
  1861. {
  1862. if (!strcmp(prog_identifier_from_cmdline,"specfnu")) dz->process = SPECFNU;
  1863. else {
  1864. sprintf(errstr,"Unknown program identification string '%s'\n",prog_identifier_from_cmdline);
  1865. return(USAGE_ONLY);
  1866. }
  1867. return(FINISHED);
  1868. }
  1869. /******************************** USAGE1 ********************************/
  1870. int usage1(void)
  1871. {
  1872. usage2("specfnu");
  1873. return(USAGE_ONLY);
  1874. }
  1875. /******************************** USAGE2 ********************************/
  1876. int usage2(char *str)
  1877. {
  1878. if(!strcmp(str,"specfnu")) {
  1879. fprintf(stdout,"\n"
  1880. "USAGE: specfnu specfnu 1-23 inanalfile outfile [params]\n"
  1881. "\n"
  1882. "Modify spectral shape in relation to formant peaks, or show formant data.\n"
  1883. "\n"
  1884. "MODE 1: NARROW FORMANTS: Steepen skirts of formant peaks by power factor.\n"
  1885. "MODE 2: SQUEEZE SPECTRUM: Squeeze the spectrum around specified formant.\n"
  1886. "MODE 3: INVERT FORMANTS: Formant peaks become troughs, and troughs peaks.\n"
  1887. "MODE 4: ROTATE FORMANTS: Formant peaks & frqs move up (or down) spectrum\n"
  1888. " reappearing at foot(top) on reaching fmnts edge.\n"
  1889. "MODE 5: SPECTRAL NEGATIVE: Spectral values inverted for each channel.\n"
  1890. "MODE 6: SUPPRESS FORMANTS: Suppresses the selected formant(s).\n"
  1891. "MODE 7: GENERATE FILTER: Output Varibank filtdata based on formant peaks.\n"
  1892. "MODE 8: MOVE FORMANTS BY: Displace individual formants by a Hz value.\n"
  1893. "MODE 9: MOVE FORMANTS TO: Displace individual formants to specified frqs.\n"
  1894. "MODE 10: ARPEGGIATE: Arppegiate partials of sound, under formants.\n"
  1895. "MODE 11: OCTAVE-SHIFT: Octave-shift pitch of sound, under formants.\n"
  1896. "MODE 12: TRANSPOSE: Transpose pitch of sound, under formants.\n"
  1897. "MODE 13: FREQ-SHIFT: Frequency shift partials of src, under formants.\n"
  1898. "MODE 14: RESPACE PARTIALS: Respace partials of sound, under formants.\n"
  1899. "MODE 15: PITCH-INVERT: Invert pitch of sound, under formants.\n"
  1900. "MODE 16: PITCH-EXAGG/SMOOTH: Exaggerate/Smooth pitchline, under formants.\n"
  1901. "MODE 17: PITCH-QUANTISE: Force pitch onto pitch field, under formants.\n"
  1902. "MODE 18: PITCH-RANDOMISE: Randomise pitch of src, under formants.\n"
  1903. "MODE 19: RANDOMISE PARTIALS: Random shift partials of sound, under formants.\n"
  1904. "MODE 20: SEE SPEC ENVELOPES: Outputs viewable (not playable) sndfile.\n"
  1905. "MODE 21: SEE SPEC PEAKS/TROFS:Print textfile of frqs of peaks+trofs per window.\n"
  1906. "MODE 22: GET LOUDNESS TROFS: Print textfile of times-of-trofs between syllabs.\n"
  1907. "MODE 23: SINE SPEECH: Single sine wave repesenting each formant.\n"
  1908. "\n"
  1909. "Type \"specfnu specfnu 1\" for more info on NARROW FORMANTS.... etc.\n"
  1910. "\n"
  1911. "Spectral window-size: Small window or Large window ???\n"
  1912. "\n"
  1913. "If process uses \"Force fundamental\" flag, Large window will find fundamental\n"
  1914. "whereas Small window may not.\n");
  1915. } else
  1916. fprintf(stdout,"Unknown option '%s'\n",str);
  1917. return(USAGE_ONLY);
  1918. }
  1919. /******************************** USAGE3 ********************************/
  1920. int usage3(char *str1,char *str2)
  1921. {
  1922. if(!strcmp(str2,"1")) {
  1923. fprintf(stdout,"\n"
  1924. "MODE 1: NARROW FORMANTS: Steepens skirts of formant peaks by power factor.\n"
  1925. "\n"
  1926. "USAGE: specfnu specfnu 1 inanalfil outanalfil narrow\n"
  1927. " [-ggain] [-ooff] [-t] [-f] [-s] [-x|-k] [-r]\n"
  1928. "\n"
  1929. "NARROW Narrowing of individual formant peaks. Range 1 to 1000. Timevariable.\n"
  1930. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1931. "OFF Suppress the listed formants. \"OFF\" can be any combination of\n"
  1932. " \"1\",\"2\",\"3\" & \"4\" but not all of them, and with no repetitions.\n"
  1933. "-t Zero top of spectrum (above fourth formant).\n"
  1934. "-f Force lowest formant to use fundamental frq as peak.\n"
  1935. "-s Use short-window for extracting spectral envelope.\n"
  1936. "-x Exclude non-harmonic partials.\n"
  1937. "-k Kill harmonic partials.\n"
  1938. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1939. } else if(!strcmp(str2,"2")) {
  1940. fprintf(stdout,"\n"
  1941. "MODE 2: SQUEEZE SPECTRUM AROUND FORMANT: Squeeze around specified formant.\n"
  1942. "\n"
  1943. "USAGE: specfnu specfnu 2 inanal outanal squeeze centre\n"
  1944. " [-ggain] [-t] [-f] [-s] [-x|-k] [-r]\n"
  1945. "\n"
  1946. "SQUEEZE Squeeze factor. Range 1 to 10. Timevariable.\n"
  1947. "CENTRE Formant peak at centre of squeeze. (range 1 to 4)\n"
  1948. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1949. "-t Squeeze around trough above specified peak.\n"
  1950. "-f Force lowest formant to use fundamental frq as peak.\n"
  1951. "-s Use short-window for extracting spectral envelope.\n"
  1952. "-x Exclude non-harmonic partials.\n"
  1953. "-k Kill harmonic partials.\n"
  1954. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1955. } else if(!strcmp(str2,"3")) {
  1956. fprintf(stdout,"\n"
  1957. "MODE 3: INVERT FORMANTS: Formant peaks become troughs, and troughs peaks.\n"
  1958. "\n"
  1959. "USAGE: specfnu specfnu 3 inanal outanal vibrate [-ggain] [-s] [-x|-k] [-r]\n"
  1960. "\n"
  1961. "VIBRATE If not zero, cycle btwn orig & inverted at this frq. Timevariable.\n"
  1962. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1963. "-s Use short-window for extracting spectral envelope.\n"
  1964. "-x Exclude non-harmonic partials.\n"
  1965. "-k Kill harmonic partials.\n"
  1966. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1967. } else if(!strcmp(str2,"4")) {
  1968. fprintf(stdout,"\n"
  1969. "MODE 4: ROTATE FORMANTS: Formant peaks & frqs move up (or down) spectrum.\n"
  1970. " reappearing at foot (top) of formant-area, when they reach its edge.\n"
  1971. "\n"
  1972. "USAGE: specfnu specfnu 4 inanal outanal rspeed [-ggain] [-s] [-x|-k] [-r]\n"
  1973. "\n"
  1974. "RSPEED How quickly the spectrum rotates, e.g. 2 = twice every second.\n"
  1975. " Range -300 to 300 rotations per second. Timevariable.\n"
  1976. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1977. "-s Use short-window for extracting spectral envelope.\n"
  1978. "-x Exclude non-harmonic partials.\n"
  1979. "-k Kill harmonic partials.\n"
  1980. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  1981. } else if(!strcmp(str2,"5")) {
  1982. fprintf(stdout,"\n"
  1983. "MODE 5: SPECTRAL NEGATIVE: Spectral values inverted for each channel.\n"
  1984. "\n"
  1985. "USAGE: specfnu specfnu 5 inanal outanal [-ggain] [-f]\n"
  1986. "\n"
  1987. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  1988. "-f \"Flat\" : does not re-envelope the output spectrum.\n");
  1989. } else if(!strcmp(str2,"6")) {
  1990. fprintf(stdout,"\n"
  1991. "MODE 6: SUPPRESS FORMANTS: Suppresses the selected formants.\n"
  1992. "\n"
  1993. "USAGE: specfnu specfnu 6 inanalfile outanalfile formantlist [-ggain] [-s] [-x]\n"
  1994. "\n"
  1995. "FORMANTLIST which of (4) formants to suppress. e.g. \"1\" means suppress 1st,\n"
  1996. " while \"134\" means suppress 1st, 3rd and 4th.\n"
  1997. "GAIN Amplitude gain attenuation. (Range 0.1 to 10).\n"
  1998. "-s Use short-window for extracting spectral envelope.\n"
  1999. "-x Exclude non-harmonic partials.\n");
  2000. } else if(!strcmp(str2,"7")) {
  2001. fprintf(stdout,"\n"
  2002. "MODE 7: GENERATE FILTER(S) FROM FORMANT(S): Outputs varibank filter data textfile.\n"
  2003. "\n"
  2004. "USAGE: specfnu specfnu 7 inanalfile outfiltfile datafile filtcnt\n"
  2005. " [-bbelow] [-k|-i] [-f] [-s]\n"
  2006. "\n"
  2007. "DATAFILE Textfile containing.\n"
  2008. " (1) List of times at which src to be divided into blocks for analysis.\n"
  2009. " Resulting filter step-changes between vals created from each block.\n"
  2010. " Value ZERO means use the entire source to make 1 fixed filter.\n"
  2011. " (2) Data about grid on which pitches you are searching for must lie.\n"
  2012. " There must first be a marker indicating the grid type. These are..\n"
  2013. " #HS: Followed by listed MIDI pitches to search for.\n"
  2014. " #HF: Followed by listed MIDI pitches to search for IN ALL OCTAVES.\n"
  2015. " #SCALE: Followed by just TWO values.\n"
  2016. " (a) the number of equal pitch divisions in an octave.\n"
  2017. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2018. " #ELACS: Followed by just THREE values.\n"
  2019. " (a) Size of \"octave\" in (possibly fractional) semitones.\n"
  2020. " (b) the number of equal pitch divisions in \"octave\".\n"
  2021. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2022. "FILTCNT (Default value 1). (Max) No. peaks from each formant to use.\n"
  2023. "BELOW Try to ensure 1 (or more) pitches below MIDI value \"below\".\n"
  2024. "-k Keep relative (summed) loudnesses of peaks as part of filter design.\n"
  2025. "-i Keep inverse of loudnesses as part of filter design.\n"
  2026. " Default. All filter amplitudes set to 1.0\n"
  2027. "-f Force fundamental as pitch in lowest formant.\n"
  2028. "-s Use short-window for extracting spectral envelope.\n"
  2029. "\n"
  2030. "With time-varying filter, transitions between time blocks can be extreme.\n"
  2031. "Wise to cut input into segments and produce fixed filters for each,\n"
  2032. "OR pre-envelope THE input file, to zero the level around transitions\n"
  2033. "deriving appropriate envelope times from the filter file times.\n");
  2034. } else if(!strcmp(str2,"8")) {
  2035. fprintf(stdout,"\n"
  2036. "MODE 8: MOVE FORMANTS BY: Displace individual formants.\n"
  2037. "\n"
  2038. "USAGE: specfnu specfnu 8 inanal outanal mov1 mov2 mov3 mov4\n"
  2039. " [-ggain] [-t] [-s] [-x|-k] [-r]\n"
  2040. "\n"
  2041. "MOV1 Frq displacement, up or down, of formant 1. Timevariable.\n"
  2042. "MOV2,3,4 Similarly for other formants.\n"
  2043. "(Formants moving below zero or above nyquist/2 will disappear).\n"
  2044. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2045. "-t Zero top of spectrum.\n"
  2046. "-s Use short-window for extracting spectral envelope.\n"
  2047. "-x Exclude non-harmonic partials.\n"
  2048. "-k Kill harmonic partials.\n"
  2049. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  2050. } else if(!strcmp(str2,"9")) {
  2051. fprintf(stdout,"\n"
  2052. "MODE 9: MOVE FORMANTS TO: Displace individual formants.\n"
  2053. "\n"
  2054. "USAGE: specfnu specfnu 9 inanal outanal frq1 frq2 frq2 frq4\n"
  2055. " [-ggain] [-t] [-s] [-n] [-x|-k] [-r]\n"
  2056. "\n"
  2057. "FRQ1 New frq of formant 1. Timevariable.\n"
  2058. "FRQ2,3,4 Similarly for other formants.\n"
  2059. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2060. "-t Zero top of spectrum.\n"
  2061. "-n Use narrow formant bands.\n"
  2062. " Using narrow bands can give counterintuitive results.\n"
  2063. " Doesn't capture so many harmonic peaks, so sounds duller.\n"
  2064. "-s Use short-window for extracting spectral envelope.\n"
  2065. "-x Exclude non-harmonic partials.\n"
  2066. "-k Kill harmonic partials.\n"
  2067. "-r Replace unpitched (or extremely quiet) windows by silence.\n");
  2068. } else if(!strcmp(str2,"10")) {
  2069. fprintf(stdout,"\n"
  2070. "MODE 10: ARPEGGIATE SPECTRUM: Arpeggiate spectrum of source, under formants.\n"
  2071. "\n"
  2072. "USAGE: specfnu specfnu 10 inanal outanal arprate\n"
  2073. " [-ggain] [-s] [-x] [-r] [-d|-c]\n"
  2074. "\n"
  2075. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2076. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2077. "-s Use short-window for extracting spectral envelope.\n"
  2078. "-x Exclude non-harmonic partials.\n"
  2079. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2080. "-d Arpeggiate downwards (default upwards).\n"
  2081. "-c Arpeggiate up and down (default upwards).\n");
  2082. } else if(!strcmp(str2,"11")) {
  2083. fprintf(stdout,"\n"
  2084. "MODE 11: OCTAVE-SHIFT UNDER FORMANTS: Octave-shift src spectrum, under formants.\n"
  2085. "\n"
  2086. "USAGE: specfnu specfnu 11 inanal outanal octshift \n"
  2087. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2088. "\n"
  2089. "OCTSHIFT 8va shift (Range -4 to + 4). (Timevariable).\n"
  2090. "\n"
  2091. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2092. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2093. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2094. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2095. "-s Use short-window for extracting spectral envelope.\n"
  2096. "-x Exclude non-harmonic partials.\n"
  2097. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2098. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2099. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2100. "-f If transposing downwards, fill spectrum top with extra harmonics.\n");
  2101. } else if(!strcmp(str2,"12")) {
  2102. fprintf(stdout,"\n"
  2103. "MODE 12: TRANSPOSE UNDER FORMANTS: tranpose spectrum of src, under formants.\n"
  2104. "\n"
  2105. "USAGE: specfnu specfnu 12 inanal outanal transpos \n"
  2106. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2107. "\n"
  2108. "TRANSPOS semitone shift (Range -48 to + 48). (Timevariable).\n"
  2109. "\n"
  2110. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2111. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2112. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2113. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2114. "-s Use short-window for extracting spectral envelope.\n"
  2115. "-x Exclude non-harmonic partials.\n"
  2116. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2117. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2118. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2119. "-f If transposing downwards, fill spectrum top with extra harmonics.\n");
  2120. } else if(!strcmp(str2,"13")) {
  2121. fprintf(stdout,"\n"
  2122. "MODE 13: FRQSHIFT UNDER FORMANTS: Frqshift src spectrum of under formants.\n"
  2123. "\n"
  2124. "USAGE: specfnu specfnu 13 inanal outanal frqshift\n"
  2125. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2126. "\n"
  2127. "FRQSHIFT Frequency shift(Hz) (Range -1000 to +1000). (Timevariable).\n"
  2128. "\n"
  2129. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2130. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2131. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2132. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2133. "-s Use short-window for extracting spectral envelope.\n"
  2134. "-x Exclude non-harmonic partials.\n"
  2135. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2136. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2137. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2138. "-f If shifting down, fill spectrum top with extra shifted partials.\n");
  2139. } else if(!strcmp(str2,"14")) {
  2140. fprintf(stdout,"\n"
  2141. "MODE 14: RESPACE PARTIALS UNDER FORMANTS: Respace partials in src spectrum,\n"
  2142. " retaining formants.\n"
  2143. "\n"
  2144. "USAGE: specfnu specfnu 14 inanal outanal respace\n"
  2145. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n"
  2146. "\n"
  2147. "RESPACE New frq spacing of partials (Hz) (Range 1 to 1000).\n"
  2148. " (Timevariable).\n"
  2149. "\n"
  2150. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2151. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2152. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2153. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2154. "-s Use short-window for extracting spectral envelope.\n"
  2155. "-x Exclude non-harmonic partials.\n"
  2156. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2157. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2158. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2159. "-f If narrowed spacing, fill spectrum top with extra shifted partials.\n");
  2160. } else if(!strcmp(str2,"15")) {
  2161. fprintf(stdout,"\n"
  2162. "MODE 15: PITCH-INVERT UNDER FORMANTS: Invert pitch of src, under formants.\n"
  2163. "\n"
  2164. "USAGE: specfnu specfnu 15 inanal outanal map about [-ggain] [-parprate]\n"
  2165. " [-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c]\n"
  2166. "\n"
  2167. "MAP Set map to ZERO if no mapping is required..OTHERWISE\n"
  2168. " map is a textfile of paired values showing how intervals\n"
  2169. " (in, possibly fractional, SEMITONES)\n"
  2170. " are to be mapped onto their inversions.\n"
  2171. " Range +-%0lf semitones (+- %.0lf octaves).\n"
  2172. "\n"
  2173. "ABOUT Pitch about which to invert pitch of src (Range %d to %d).\n"
  2174. " Pitch as MIDI, with possibly fractional val. (Timevariable).\n"
  2175. " If value zero entered, uses the mean pitch of the input.\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. "-s Use short-window for extracting spectral envelope.\n"
  2184. "-x Exclude non-harmonic partials.\n"
  2185. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2186. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2187. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n",MAXINTRANGE,MAXINTRANGE/SEMITONES_PER_OCTAVE,SPEC_MIDIMIN,MIDIMAX);
  2188. } else if(!strcmp(str2,"16")) {
  2189. fprintf(stdout,"\n"
  2190. "MODE 16: PITCH-EXAGGERATE/SMOOTH UNDER FORMANTS: Exaggerate/Smooth pitch-line,\n"
  2191. " retaining the formants.\n"
  2192. "\n"
  2193. "USAGE: specfnu specfnu 16 inanal outanal about rang [-ggain] [-parprate]\n"
  2194. " [-llocut] [-hhicut] [-blopch] [-thipch] [-T] [-F] [-M] [-A] [-B]\n"
  2195. " [-s] [-x] [-r] [-d|-c]\n"
  2196. "\n"
  2197. "ABOUT Pitch about which to exagg/smooth pitchline of src (Range %d to %d).\n"
  2198. " Pitch as MIDI, with possibly fractional val. (Timevariable).\n"
  2199. " If value zero entered, uses the mean pitch of the input.\n"
  2200. "RANG Expand or Contract Range of pitchline. (Range 0 - 1).\n"
  2201. "\n"
  2202. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2203. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2204. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2205. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2206. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2207. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2208. "-T Tie to TOP of pitch range.\n"
  2209. "-F Tie to FOOT of pitch range.\n"
  2210. "-M (only with \"-T\" and \"M\" flags) also Tie to range middle.\n"
  2211. "-A Do range change ABOVE mean only.\n"
  2212. "-B Do range change BELOW mean only.\n"
  2213. "-s Use short-window for extracting spectral envelope.\n"
  2214. "-x Exclude non-harmonic partials.\n"
  2215. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2216. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2217. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n",SPEC_MIDIMIN,MIDIMAX);
  2218. } else if(!strcmp(str2,"17")) {
  2219. fprintf(stdout,"\n"
  2220. "MODE 17: QUANTISE PITCH: Force source onto a specified pitch field.\n"
  2221. "\n"
  2222. "USAGE: specfnu specfnu 17 inanal outanal datafile [-ggain] [-parprate]\n"
  2223. " [-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c] [-o] [-n]\n"
  2224. "\n"
  2225. "DATAFILE Textfile containing data about pitches to quantise to.\n"
  2226. " There must first be a marker indicating the grid type. These are..\n"
  2227. " #HS: Followed by listed MIDI pitches to quantise to.\n"
  2228. " #HF: Followed by listed MIDI pitches to quantise to IN ALL OCTAVES.\n"
  2229. " #THF: Followed by lines each with time + list of MIDI pitches.\n"
  2230. " 1st time must be zero & times must increase.\n"
  2231. " Each MIDI list must be the same length.\n"
  2232. " To change no of pitches from line to line, duplicate values.\n"
  2233. " #SCALE: Followed by just TWO values.\n"
  2234. " (a) the number of equal pitch divisions in an octave.\n"
  2235. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2236. " #ELACS: Followed by just THREE values.\n"
  2237. " (a) Size of \"pseudo-octave\" in (possibly fractional) semitones.\n"
  2238. " (b) the number of equal pitch divisions in peudo-octave.\n"
  2239. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2240. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2241. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2242. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2243. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2244. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2245. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2246. "-s Use short-window for extracting spectral envelope.\n"
  2247. "-x Exclude non-harmonic partials.\n"
  2248. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2249. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2250. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2251. "-o Allow ORNAMENTS in the quantised pitch-line.\n"
  2252. "-n No smoothing of transitions between pitches.\n");
  2253. } else if(!strcmp(str2,"18")) {
  2254. fprintf(stdout,"\n"
  2255. "MODE 18: PITCH RANDOMISE: Randomise pitch of src.\n"
  2256. "\n"
  2257. "USAGE: specfnu specfnu 18 inanal outanal datafile range slew [-ggain] [-parprate]\n"
  2258. " [-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c] [-o] [-n] [-k]]\n"
  2259. "\n"
  2260. "DATAFILE If this set to ZERO, no pre-quantisation of pitch takes place.\n"
  2261. " Otherwise, this is textfile of data about pitches to quantise to.\n"
  2262. " There must first be a marker indicating the grid type. These are..\n"
  2263. " #HS: Followed by listed MIDI pitches to quantise to.\n"
  2264. " #HF: Followed by listed MIDI pitches to quantise to IN ALL OCTAVES.\n"
  2265. " #THF: Followed by lines each with time + list of MIDI pitches.\n"
  2266. " 1st time must be zero & times must increase.\n"
  2267. " Each MIDI list must be the same length.\n"
  2268. " To change no of pitches from line to line, duplicate values.\n"
  2269. " #SCALE: Followed by just TWO values.\n"
  2270. " (a) the number of equal pitch divisions in an octave.\n"
  2271. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2272. " #ELACS: Followed by just THREE values.\n"
  2273. " (a) Size of \"pseudo-octave\" in (possibly fractional) semitones.\n"
  2274. " (b) the number of equal pitch divisions in peudo-octave.\n"
  2275. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2276. "RANGE semitone range within which random offsets generated. (Range 0 to %d)\n"
  2277. "SLEW Relationship between (possible) upward & downward rand variation.\n"
  2278. " e.g. 2: uprange = 2 * downrange 0.5: uprange = 0.5 * downrange.\n"
  2279. " Ranges 0.1 to 10. (Value 1 has no effect).\n"
  2280. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2281. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2282. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2283. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2284. "LOPCH Minimum acceptable pitch (MIDI, possibly fractional).\n"
  2285. "HIPCH Maximum acceptable pitch (MIDI, possibly fractional).\n"
  2286. "-s Use short-window for extracting spectral envelope.\n"
  2287. "-x Exclude non-harmonic partials.\n"
  2288. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2289. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2290. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n"
  2291. "-o Open up FAST MOVEMENT in the quantised pitch-line.\n"
  2292. "-n No smoothing of transitions between pitches.\n"
  2293. "-k Kill-off formant reshaping.\n",RANDPITCHMAX);
  2294. } else if(!strcmp(str2,"19")) {
  2295. fprintf(stdout,"\n"
  2296. "MODE 19: RANDOMISE SPECTRUM UNDER FORMANTS: Randomise spectrum, under formants.\n"
  2297. "\n"
  2298. "USAGE: specfnu specfnu 19 inanal outanal rand\n"
  2299. " [-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n"
  2300. "\n"
  2301. "RAND Randomisation of partial frequencies (Range 0 to 1).\n"
  2302. " (Timevariable).\n"
  2303. "\n"
  2304. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2305. "ARPRATE Rate of arpeggiation of spectrum (Range -50 to +50 Hz).\n"
  2306. "LOCUT Cut off frequencies below this. (range 0 to 10000)\n"
  2307. "HICUT Cut off frequencies above this. (range 50 to 10000)\n"
  2308. "-s Use short-window for extracting spectral envelope.\n"
  2309. "-x Exclude non-harmonic partials.\n"
  2310. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2311. "-d Arpeggiate downwards (dflt upwards). (Only when \"arprate\" > 0).\n"
  2312. "-c Arpeggiate up and down (dflt upwards). (Only when \"arprate\" > 0).\n");
  2313. } else if(!strcmp(str2,"20")) {
  2314. fprintf(stdout,"\n"
  2315. "MODE 20: SEE SPECTRAL ENVELOPES: Outputs viewable (not playable) sndfile\n"
  2316. " showing spectral envelope at each window\n"
  2317. " as a block of +ve samples.\n"
  2318. "\n"
  2319. "USAGE: specfnu specfnu 20 inanalfile outpseudosndfile [-s]\n"
  2320. "\n"
  2321. "-s Use short-window for extracting spectral envelope.\n");
  2322. } else if(!strcmp(str2,"21")) {
  2323. fprintf(stdout,"\n"
  2324. "MODE 21: SEE SPECTRAL PEAKS & TROUGHS: Frqs of troughs/peaks in each window\n"
  2325. " printed to textfile, in the format...\n"
  2326. "\n"
  2327. " \"Trough PEAK-1 Trough PEAK-2 Trough PEAK-3 Trough PEAK-4 Trough\"\n"
  2328. "\n"
  2329. "USAGE: specfnu specfnu 21 inanalfile outtextfile [-s]\n"
  2330. "\n"
  2331. "-s Use short-window for extracting spectral envelope.\n");
  2332. } else if(!strcmp(str2,"22")) {
  2333. fprintf(stdout,"\n"
  2334. "MODE 22: LIST TIMES OF TROUGHS BETWEEN SYLLABLES: Times printed to textfile.\n"
  2335. "\n"
  2336. "Will usually need post-correction \"by hand\".\n"
  2337. "\n"
  2338. "USAGE: specfnu specfnu 22 inanal outtextfile [-ssyldur] [-ppktrof] [-P|-B]\n"
  2339. "\n"
  2340. "SYLDUR Min acceptable duration for a syllable (default %.04lf)\n"
  2341. "PKTROF Min height of peak above bracketing trofs (default %.04lf).\n"
  2342. " (Maximum possible height is 1.0).\n"
  2343. "-P Get peaks.\n"
  2344. "-B Get both troughs and peaks,\n",MIN_SYLLAB_DUR,MIN_PEAKTROF_GAP);
  2345. } else if(!strcmp(str2,"23")) {
  2346. fprintf(stdout,"\n"
  2347. "MODE 23: SINE SPEECH: Convert formant frqs to sinus tones.\n"
  2348. "\n"
  2349. "USAGE: specfnu specfnu 23 inanalfile outanalfile hffile sining [-again]\n"
  2350. "[-bamp1] [-camp2] [-damp3] [-eamp4] [-nqdep1] [-oqdep2] [-pdep3] [-qqdep4]\n"
  2351. "[-s] [-f] [-r] [-S]\n"
  2352. "\n"
  2353. "HFFILE If this set to ZERO, no pitch quantisation takes place.\n"
  2354. " Otherwise, this is textfile of data about pitches to quantise to.\n"
  2355. " There must first be a marker indicating the grid type. These are..\n"
  2356. " #HS: Followed by listed MIDI pitches to quantise to.\n"
  2357. " #HF: Followed by listed MIDI pitches to quantise to IN ALL OCTAVES.\n"
  2358. " #THF: Followed by lines each with time + list of MIDI pitches.\n"
  2359. " 1st time must be zero & times must increase.\n"
  2360. " Each MIDI list must be the same length.\n"
  2361. " To change no of pitches from line to line, duplicate values.\n"
  2362. " #SCALE: Followed by just TWO values.\n"
  2363. " (a) the number of equal pitch divisions in an octave.\n"
  2364. " (b) MIDI pitch of any pitch to tune the scales to.\n"
  2365. " #ELACS: Followed by just THREE values.\n"
  2366. " (a) Size of \"pseudo-octave\" in (possibly fractional) semitones.\n"
  2367. " (b) the number of equal pitch divisions in peudo-octave.\n"
  2368. " (c) MIDI pitch of any pitch to tune the scales to.\n"
  2369. "\n"
  2370. "GAIN Output gain or attenuation. (Range 0.01 to 10)\n"
  2371. "SINING Degree of sinusoidisation. Range 0 to 1.\n"
  2372. "AMP1 Relative gain or attenuation of formant1. (Range 0.01 to 10)\n"
  2373. " AMP2,AMP3,AMP4 similar for the other formants.\n"
  2374. "DEP1 If HF applied, how strongly to force pitches formant1 to hf (Range 0-1).\n"
  2375. "DEP2, DEP3, DEP4 Similarly for other formant bands.\n"
  2376. "-s Use short-window for extracting spectral envelope.\n"
  2377. "-f Force lowest formant to use fundamental frq as peak.\n"
  2378. "-r Replace unpitched (or extremely quiet) windows by silence.\n"
  2379. "-S Smoothing between pitches in formant traces.\n");
  2380. } else
  2381. fprintf(stdout,"Unknown mode '%s'\n",str2);
  2382. return(USAGE_ONLY);
  2383. }
  2384. /******************************** USAGE4 ********************************/
  2385. int usage4(int mode)
  2386. {
  2387. fprintf(stdout,"\nToo few parameters ");
  2388. switch(mode) {
  2389. case(0):
  2390. fprintf(stdout,"NARROW FORMANTS\n\n");
  2391. fprintf(stdout,"USAGE: specfnu specfnu 1 inanal outanal narrow\n");
  2392. fprintf(stdout,"[-ggain] [-ooff] [-t] [-f] [-s] [-x|-k] [-r]\n");
  2393. break;
  2394. case(1):
  2395. fprintf(stdout,"SQUEEZE SPECTRUM AROUND FORMANT\n\n");
  2396. fprintf(stdout,"USAGE: specfnu specfnu 2 inanal outanal squeeze centre\n");
  2397. fprintf(stdout,"[-ggain] [-t] [-f] [-s] [-x|-k] [-r]\n");
  2398. break;
  2399. case(2):
  2400. fprintf(stdout,"INVERT FORMANTS\n\n");
  2401. fprintf(stdout,"USAGE: specfnu specfnu 3 inanal outanal vibrate [-ggain] [-s] [-x|-k] [-r]\n");
  2402. break;
  2403. case(3):
  2404. fprintf(stdout,"ROTATE FORMANTS\n\n");
  2405. fprintf(stdout,"USAGE: specfnu specfnu 4 inanal outanal rspeed [-ggain] [-s] [-x|-k] [-r]\n");
  2406. break;
  2407. case(4):
  2408. fprintf(stdout,"SPECTRAL NEGATIVE\n\n");
  2409. fprintf(stdout,"USAGE: specfnu specfnu 5 inanal outanal [-ggain] [-f]\n");
  2410. break;
  2411. case(5):
  2412. fprintf(stdout,"SUPPRESS FORMANTS\n\n");
  2413. fprintf(stdout,"USAGE: specfnu specfnu 6 inanal outanal formantlist [-ggain] [-s] [-x]\n");
  2414. break;
  2415. case(6):
  2416. fprintf(stdout,"GENERATE FILTER(S) FROM FORMANT(S)\n\n");
  2417. fprintf(stdout,"USAGE: specfnu specfnu 7 inanal outfiltfil datafile filtcnt\n");
  2418. fprintf(stdout,"[-bbelow] [-k|-i] [-f] [-s]\n");
  2419. break;
  2420. case(7):
  2421. fprintf(stdout,"MOVE FORMANTS BY\n\n");
  2422. fprintf(stdout,"USAGE: specfnu specfnu 8 inanal outanal mov1 mov2 mov2 mov4\n");
  2423. fprintf(stdout,"[-ggain] [-t] [-s] [-x|-k] [-r]\n");
  2424. break;
  2425. case(8):
  2426. fprintf(stdout,"MOVE FORMANTS TO\n\n");
  2427. fprintf(stdout,"USAGE: specfnu specfnu 9 inanal outanal frq1 frq2 frq2 frq4\n");
  2428. fprintf(stdout,"[-ggain] [-t] [-s] [-n] [-x|-k] [-r]\n");
  2429. break;
  2430. case(9):
  2431. fprintf(stdout,"ARPEGGIATE SPECTRUM \n\n");
  2432. fprintf(stdout,"USAGE: specfnu specfnu 10 inanal outanal arprate\n");
  2433. fprintf(stdout,"[-ggain] [-s] [-x] [-r] [-d|-c]\n");
  2434. break;
  2435. case(10):
  2436. fprintf(stdout,"OCTAVE-SHIFT UNDER FORMANTS\n\n");
  2437. fprintf(stdout,"USAGE: specfnu specfnu 11 inanal outanal octshift\n");
  2438. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2439. break;
  2440. case(11):
  2441. fprintf(stdout,"TRANSPOSE UNDER FORMANTS \n\n");
  2442. fprintf(stdout,"USAGE: specfnu specfnu 12 inanal outanal transpos\n");
  2443. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2444. break;
  2445. case(12):
  2446. fprintf(stdout,"FRQSHIFT UNDER FORMANTS \n\n");
  2447. fprintf(stdout,"USAGE: specfnu specfnu 13 inanal outanal frqshift\n");
  2448. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2449. break;
  2450. case(13):
  2451. fprintf(stdout,"RESPACE PARTIALS UNDER FORMANTS \n\n");
  2452. fprintf(stdout,"USAGE: specfnu specfnu 14 inanal outanal respace\n");
  2453. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c] [-f]\n");
  2454. break;
  2455. case(14):
  2456. fprintf(stdout,"PITCH INVERT UNDER FORMANTS \n\n");
  2457. fprintf(stdout,"USAGE: specfnu specfnu 15 inanal outanal about\n");
  2458. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n");
  2459. break;
  2460. case(15):
  2461. fprintf(stdout,"PITCH EXAGGERATE UNDER FORMANTS \n\n");
  2462. fprintf(stdout,"USAGE: specfnu specfnu 16 inanal outanal about rang [-ggain] [-parprate]\n");
  2463. fprintf(stdout,"[-llocut] [-hhicut] [-blopch] [-thipch] [-T] [-F] [-M] [-A] [-B]\n");
  2464. fprintf(stdout,"[-s] [-x] [-r] [-d|-c]\n");
  2465. break;
  2466. case(16):
  2467. fprintf(stdout,"PITCH QUANTISE UNDER FORMANTS \n\n");
  2468. fprintf(stdout,"USAGE: specfnu specfnu 17 inanal outanal datafile [-ggain] [-parprate]\n");
  2469. fprintf(stdout,"[-llocut] [-hhicut] [-blopch] [-thipch] [-s] [-x] [-r] [-d|-c]\n");
  2470. break;
  2471. case(17):
  2472. fprintf(stdout,"RANDOMISE SPECTRUM UNDER FORMANTS \n\n");
  2473. fprintf(stdout,"USAGE: specfnu specfnu 18 inanal outanal rand\n");
  2474. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n");
  2475. break;
  2476. case(18):
  2477. fprintf(stdout,"RANDOMISE SPECTRUM UNDER FORMANTS \n\n");
  2478. fprintf(stdout,"USAGE: specfnu specfnu 19 inanal outanal rand\n");
  2479. fprintf(stdout,"[-ggain] [-parprate] [-llocut] [-hhicut] [-s] [-x] [-r] [-d|-c]\n");
  2480. break;
  2481. case(19):
  2482. fprintf(stdout,"SEE SPECTRAL ENVELOPES \n\n");
  2483. fprintf(stdout,"USAGE: specfnu specfnu 20 inanalfile outpseudosndfile [-s]\n");
  2484. break;
  2485. case(20):
  2486. fprintf(stdout,"SEE SPECTRAL PEAKS & TROUGHS \n\n");
  2487. fprintf(stdout,"USAGE: specfnu specfnu 21 inanalfile outtextfile [-s]\n");
  2488. break;
  2489. case(21):
  2490. fprintf(stdout,"LIST TIMES OF TROUGHS BETWEEN SYLLABLES \n\n");
  2491. fprintf(stdout,"USAGE: specfnu specfnu 22 inanal outtextfile [-ssyldur] [-ppktrof] [-P|-B]\n");
  2492. break;
  2493. case(22):
  2494. fprintf(stdout,"SINE SPEECH \n\n");
  2495. fprintf(stdout,"USAGE: specfnu specfnu 23 inanalfile outanalfile hffile sining [-again]\n");
  2496. fprintf(stdout,"[-bamp1] [-camp2] [-damp3] [-eamp4] [-nqdep1] [-oqdep2] [-pdep3] [-qqdep4]\n");
  2497. fprintf(stdout,"[-s] [-f] [-r] [-S]\n");
  2498. break;
  2499. }
  2500. fflush(stdout);
  2501. return(USAGE_ONLY);
  2502. }
  2503. /************************ GET_THE_MODE_NO *********************/
  2504. int get_the_mode_no(char *str, dataptr dz)
  2505. {
  2506. if(sscanf(str,"%d",&dz->mode)!=1) {
  2507. sprintf(errstr,"Cannot read mode of program.\n");
  2508. return(USAGE_ONLY);
  2509. }
  2510. if(dz->mode <= 0 || dz->mode > dz->maxmode) {
  2511. sprintf(errstr,"Program mode value [%d] is out of range [1 - %d].\n",dz->mode,dz->maxmode);
  2512. return(USAGE_ONLY);
  2513. }
  2514. dz->mode--; /* CHANGE TO INTERNAL REPRESENTATION OF MODE NO */
  2515. return(FINISHED);
  2516. }
  2517. /************************ FORCE_EXTENSION *********************/
  2518. void force_extension(int type,char *filename)
  2519. {
  2520. char *q, *p = filename;
  2521. int doit = 0;
  2522. while(*p != '.') {
  2523. p++;
  2524. if(*p == ENDOFSTR)
  2525. break;
  2526. }
  2527. if(*p == ENDOFSTR) {
  2528. switch(type) {
  2529. case(0): strcat(filename,".wav"); break;
  2530. case(1): strcat(filename,".txt"); break;
  2531. }
  2532. } else {
  2533. p++;
  2534. q = p;
  2535. switch(type) {
  2536. case(0):
  2537. if(*q++ != 'w')
  2538. doit = 1; //RWD all 4 cases, needed assignment
  2539. else {
  2540. if(*q++ != 'a')
  2541. doit = 1;
  2542. else {
  2543. if(*q++ != 'v')
  2544. doit = 1;
  2545. else {
  2546. if(*q != ENDOFSTR)
  2547. doit = 1;
  2548. }
  2549. }
  2550. }
  2551. break;
  2552. case(1):
  2553. if(*q++ != 't')
  2554. doit = 1;
  2555. else {
  2556. if(*q++ != 'x')
  2557. doit = 1;
  2558. else {
  2559. if(*q++ != 't')
  2560. doit = 1;
  2561. else {
  2562. if(*q != ENDOFSTR)
  2563. doit = 1;
  2564. }
  2565. }
  2566. }
  2567. break;
  2568. }
  2569. if(doit) {
  2570. *p = ENDOFSTR;
  2571. switch(type) {
  2572. case(0): strcat(filename,"wav"); break;
  2573. case(1): strcat(filename,"txt"); break;
  2574. }
  2575. }
  2576. }
  2577. }
  2578. /**************************** OUTER_SPECFNU_LOOP ****************************/
  2579. int outer_specfnu_loop(int contourcnt,dataptr dz)
  2580. {
  2581. int exit_status, n, zerolen, cc, vc, passno = 0, times_index, arp_param = 0, previouspk = -1, up = 1;
  2582. int windows_in_buf, inner_lpcnt;
  2583. double thisfrq, fmax = -HUGE, normaliser = 0.0;
  2584. int limit = dz->wlength * PKBLOK;
  2585. double phase = 0.0, target = 0.0, maxpitch = 0.0, minpitch = 0.0;
  2586. // Where, in the 3 processing loops, does each mode begin
  2587. switch(dz->mode) {
  2588. case(F_ARPEG):
  2589. arp_param = FARPRATE;
  2590. passno = FPREANAL;
  2591. break;
  2592. case(F_OCTSHIFT):// fall thro
  2593. case(F_TRANS): // fall thro
  2594. case(F_FRQSHIFT):// fall thro
  2595. case(F_RESPACE): // fall thro
  2596. case(F_PINVERT): // fall thro
  2597. case(F_RAND): // fall thro
  2598. case(F_PEXAGG): // fall thro
  2599. case(F_PQUANT): // fall thro
  2600. case(F_PCHRAND):
  2601. arp_param = COLRATE;
  2602. passno = FPREANAL;
  2603. break;
  2604. case(F_SYLABTROF)://fall thro
  2605. case(F_SINUS):
  2606. passno = FPREANAL;
  2607. break;
  2608. case(F_NARROW): // fall thro
  2609. case(F_SQUEEZE):// fall thro
  2610. case(F_MOVE): // fall thro
  2611. case(F_MOVE2): // fall thro
  2612. case(F_INVERT): // fall thro
  2613. case(F_ROTATE): // fall thro
  2614. case(F_SUPPRESS):// fall thro
  2615. case(F_MAKEFILT):
  2616. if(dz->needpitch)
  2617. passno = FPREANAL; // Extract pitch data (FPREANAL) before extracting formant env FSPECENV and then processing sound FPROCESS
  2618. else
  2619. passno = FSPECENV;
  2620. break;
  2621. case(F_NEGATE):
  2622. if(dz->needpitch)
  2623. passno = FPREANAL; // Extract pitch data (FPREANAL) before processing sound FPROCESS
  2624. else
  2625. passno = FPROCESS; // Otheriwise SKIP extracting formantenv (not needed) and go dircetly to FPROCESS
  2626. break;
  2627. case(F_SEE):
  2628. passno = FSPECENV; // Extract formant env FSPECENV before processing sound FPROCESS
  2629. break;
  2630. case(F_SEEPKS):
  2631. passno = FPROCESS; // Go directly to processing sound FPROCESS
  2632. break;
  2633. }
  2634. while(passno < 3) {
  2635. /* TEST *
  2636. fprintf(stderr,"passno = %d\n",passno);
  2637. * TEST */
  2638. // Which modes skip some of the processing loops?
  2639. if(passno > 0 && dz->mode == F_SYLABTROF) {
  2640. passno++;
  2641. continue; // F_SYLABTROF needs to get loudness envelope (during pitch-analysis routine) but needs nothing else;
  2642. }
  2643. if(passno == FSPECENV && dz->mode == F_NEGATE) {
  2644. passno++; // F_NEGATE may use pass0 (to get pitch), but doesn't need to get spectral peaks
  2645. continue;
  2646. }
  2647. times_index = 1;
  2648. inner_lpcnt = 0;
  2649. if(sloom)
  2650. dz->total_samps_read = 0L;
  2651. // Messaging
  2652. switch(passno) {
  2653. case(FPREANAL): // (pass 0) EXTRACTING PITCH, AND LOUDNESS-ENVELOPE
  2654. switch(dz->mode) {
  2655. case(F_MOVE): // fall thro
  2656. case(F_MOVE2): // fall thro
  2657. case(F_NEGATE): // fall thro
  2658. case(F_INVERT): // fall thro
  2659. case(F_NARROW): // fall thro
  2660. case(F_SQUEEZE): // fall thro
  2661. case(F_ROTATE): // fall thro
  2662. case(F_ARPEG): // fall thro
  2663. case(F_OCTSHIFT): // fall thro
  2664. case(F_TRANS): // fall thro
  2665. case(F_FRQSHIFT): // fall thro
  2666. case(F_RESPACE): // fall thro
  2667. case(F_PINVERT): // fall thro
  2668. case(F_PEXAGG): // fall thro
  2669. case(F_PQUANT): // fall thro
  2670. case(F_PCHRAND): // fall thro
  2671. case(F_SINUS): // fall thro
  2672. case(F_RAND): // fall thro
  2673. case(F_MAKEFILT): fprintf(stdout,"INFO: Extracting pitch contour.\n"); break;
  2674. case(F_SYLABTROF): fprintf(stdout,"INFO: Extracting loudness contour.\n"); break;
  2675. default:
  2676. sprintf(errstr,"Unknown mode in pass %d.\n",passno);
  2677. return PROGRAM_ERROR;
  2678. }
  2679. break;
  2680. case(FSPECENV): // (pass 1) GET SPECTRAL ENVELOPE
  2681. switch(dz->mode) {
  2682. case(F_SEE): fprintf(stdout,"INFO: Testing level.\n"); break;
  2683. case(F_SQUEEZE): // fall thro
  2684. case(F_SUPPRESS): // fall thro
  2685. case(F_INVERT): // fall thro
  2686. case(F_ROTATE): // fall thro
  2687. case(F_MAKEFILT): // fall thro
  2688. case(F_MOVE): // fall thro
  2689. case(F_MOVE2): // fall thro
  2690. case(F_SINUS): // fall thro
  2691. case(F_NARROW): fprintf(stdout,"INFO: Finding spectral peak data.\n"); break;
  2692. case(F_ARPEG): // fall thro
  2693. case(F_OCTSHIFT): // fall thro
  2694. case(F_TRANS): // fall thro
  2695. case(F_FRQSHIFT): // fall thro
  2696. case(F_RESPACE): // fall thro
  2697. case(F_PINVERT): // fall thro
  2698. case(F_PEXAGG): // fall thro
  2699. case(F_PQUANT): // fall thro
  2700. case(F_PCHRAND): // fall thro
  2701. case(F_RAND): fprintf(stdout,"INFO: Finding spectral envelope.\n"); break;
  2702. case(F_NEGATE): // fall thro
  2703. case(F_SEEPKS): // fall thro
  2704. case(F_SYLABTROF):
  2705. sprintf(errstr,"Should not be visited on this pass (%d).\n",passno);
  2706. return PROGRAM_ERROR;
  2707. default:
  2708. sprintf(errstr,"Unknown mode in pass %d.\n",passno);
  2709. return PROGRAM_ERROR;
  2710. }
  2711. break;
  2712. case(FPROCESS): // (pass 2) PROCESS SOUND
  2713. switch(dz->mode) {
  2714. case(F_SEE): // fall thro
  2715. case(F_MAKEFILT): // fall thro
  2716. case(F_SEEPKS): fprintf(stdout,"INFO: Writing output.\n"); break;
  2717. case(F_NARROW):
  2718. case(F_ROTATE):
  2719. case(F_SQUEEZE):
  2720. case(F_SUPPRESS):
  2721. case(F_INVERT):
  2722. case(F_NEGATE):
  2723. case(F_ARPEG): // fall thro
  2724. case(F_OCTSHIFT): // fall thro
  2725. case(F_TRANS): // fall thro
  2726. case(F_FRQSHIFT): // fall thro
  2727. case(F_RESPACE): // fall thro
  2728. case(F_PINVERT): // fall thro
  2729. case(F_PEXAGG): // fall thro
  2730. case(F_PQUANT): // fall thro
  2731. case(F_SINUS): // fall thro
  2732. case(F_PCHRAND): // fall thro
  2733. case(F_RAND): // fall thro
  2734. case(F_MOVE2): // fall thro
  2735. case(F_MOVE): fprintf(stdout,"INFO: Transforming spectrum and writing output.\n");break;
  2736. case(F_SYLABTROF):
  2737. sprintf(errstr,"Should not be visited on this pass (%d).\n",passno);
  2738. return PROGRAM_ERROR;
  2739. default:
  2740. sprintf(errstr,"Unknown mode in pass %d.\n",passno);
  2741. return PROGRAM_ERROR;
  2742. }
  2743. break;
  2744. }
  2745. fflush(stdout);
  2746. /* TEST *
  2747. fprintf(stderr,"START of OUTER LOOP passno = %d\n",passno);
  2748. * TEST */
  2749. sndseekEx(dz->ifd[0],0,0);
  2750. if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
  2751. return(exit_status);
  2752. dz->total_windows = 0;
  2753. dz->time = 0.0;
  2754. while(dz->ssampsread > 0) {
  2755. dz->flbufptr[0] = dz->bigfbuf;
  2756. windows_in_buf = dz->ssampsread/dz->wanted;
  2757. /* TEST *
  2758. fprintf(stderr,"GOING TO INNER LOOP passno = %d\n",passno);
  2759. * TEST */
  2760. 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)
  2761. return(exit_status);
  2762. if(passno == FPROCESS) { // (pass 2)
  2763. switch(dz->mode) {
  2764. case(F_SEE): // Normalise pseudosndfile output
  2765. for(n = 0;n < dz->ssampsread;n++)
  2766. dz->bigfbuf[n] = (float)(dz->bigfbuf[n] * normaliser);
  2767. break;
  2768. case(F_SEEPKS): // Output is to textfile
  2769. case(F_SYLABTROF):
  2770. case(F_MAKEFILT):
  2771. break;
  2772. default: // Write analfile output
  2773. /* TEST *
  2774. fprintf(stderr,"WRITING OUTPUT\n");
  2775. * TEST */
  2776. if((exit_status = write_samps(dz->bigfbuf,dz->ssampsread,dz))<0)
  2777. return(exit_status);
  2778. break;
  2779. }
  2780. }
  2781. if((exit_status = read_samps(dz->bigfbuf,dz)) < 0)
  2782. return(exit_status);
  2783. }
  2784. switch(passno) {
  2785. case(FPREANAL):
  2786. if(dz->mode != F_SYLABTROF) {
  2787. if((exit_status = tidy_up_pitch_data(dz))<0)
  2788. return(exit_status);
  2789. }
  2790. switch(dz->mode) {
  2791. case(F_PINVERT):// fall thro
  2792. case(F_PEXAGG):
  2793. if(dz->param[COLFLT] <= 0.0) { // No centre pivot, specified, use the mean
  2794. if((exit_status = getmeanpitch(&dz->param[COLFLT],&minpitch,&maxpitch,dz))<0)
  2795. return exit_status;
  2796. }
  2797. break;
  2798. case(F_PQUANT):
  2799. if((exit_status = pitch_quantise_all(dz))<0)
  2800. return exit_status;
  2801. break;
  2802. case(F_PCHRAND):
  2803. if(dz->quantcnt) {
  2804. if((exit_status = pitch_quantise_all(dz))<0)
  2805. return exit_status;
  2806. }
  2807. if((exit_status = pitch_randomise_all(dz))<0)
  2808. return exit_status;
  2809. break;
  2810. }
  2811. break;
  2812. case(FSPECENV): // (pass 1)
  2813. switch(dz->mode) {
  2814. case(F_SEE):
  2815. if(fmax < VERY_TINY_VAL) {
  2816. sprintf(errstr,"No significant data found in input file.\n");
  2817. return DATA_ERROR;
  2818. }
  2819. normaliser = SPECFNU_MAXLEVEL/fmax;
  2820. break;
  2821. case(F_SINUS):
  2822. if((exit_status = formants_smooth_and_quantise_all(dz))<0)
  2823. return exit_status;
  2824. break;
  2825. }
  2826. break;
  2827. case(FPROCESS): // (pass 2)
  2828. if(dz->mode == F_MAKEFILT) {
  2829. if((exit_status = build_filter(times_index,dz)) < 0)
  2830. return(exit_status);
  2831. }
  2832. break;
  2833. }
  2834. if(dz->ssampsread < 0) {
  2835. sprintf(errstr,"Sound read error.\n");
  2836. return(SYSTEM_ERROR);
  2837. }
  2838. /* TEST *
  2839. fprintf(stderr,"END of outer_loop passno = %d\n",passno);
  2840. * TEST */
  2841. if(passno == 0 && dz->mode == F_SYLABTROF) {
  2842. if((exit_status = trof_detect(dz))<0)
  2843. return(exit_status);
  2844. break;
  2845. }
  2846. passno++;
  2847. }
  2848. if(dz->mode == F_SEE || dz->mode == F_SEEPKS || dz->mode == F_MAKEFILT || dz->mode == F_SYLABTROF)
  2849. return FINISHED;
  2850. if(!dz->ischange) {
  2851. sprintf(errstr,"NO CHANGE TO THE ORIGINAL SOUND\n");
  2852. return DATA_ERROR;
  2853. }
  2854. // Write final zero buffers to avoid any end click
  2855. dz->flbufptr[0] = dz->bigfbuf;
  2856. zerolen = dz->infile->Mlen/dz->infile->Dfac;
  2857. for(n=0;n<zerolen;n++) {
  2858. memset((char *)dz->flbufptr[0],0,(size_t)dz->wanted * sizeof(float));
  2859. thisfrq = 0.0;
  2860. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  2861. dz->flbufptr[0][FREQ] = (float)thisfrq;
  2862. thisfrq += dz->chwidth;
  2863. }
  2864. dz->flbufptr[0] += dz->wanted;
  2865. }
  2866. if((exit_status = write_samps(dz->bigfbuf,zerolen * dz->wanted,dz))<0)
  2867. return(exit_status);
  2868. return FINISHED;
  2869. }
  2870. /************************** SETUP_FORMANT_ARRAYS *********************/
  2871. int setup_formant_arrays(int *contourcnt,dataptr dz)
  2872. {
  2873. int exit_status, scalefact;
  2874. int arraycnt, contour_halfbands_per_step;
  2875. dz->specenv_type = FREQWISE_FORMANTS; // Frqwise formants seem to give more obvious formant peaks (pitvchwise is multipeaky)
  2876. scalefact = (int)round((double)dz->clength/(double)CLENGTH_DEFAULT);
  2877. dz->formant_bands *= scalefact; // Width of spectral-envelope bands depends on number of anal points actually used
  2878. if((exit_status = initialise_specenv(&arraycnt,dz))<0) // Formant arrays set up here
  2879. return(exit_status);
  2880. if((exit_status = set_the_specenv_frqs(arraycnt,dz))<0) // dz->specenvcnt (& dz->infile->specenvcnt) established here
  2881. return(exit_status); // (both required in formant library functions)
  2882. dz->descriptor_samps = dz->specenvcnt * DESCRIPTOR_DATA_BLOKS;
  2883. if(is_coloring(dz)) {
  2884. if((dz->specenvamp2 = (float *)malloc(dz->specenvcnt * sizeof(float)))==NULL) {
  2885. sprintf(errstr,"INSUFFICIENT MEMORY for second formant amplitude array.\n");
  2886. return(MEMORY_ERROR);
  2887. }
  2888. }
  2889. if(*contourcnt) {
  2890. contour_halfbands_per_step = SPECFNU_LONG_FBANDS * scalefact; // Width of spectral-contour bands depends on number of anal points actually used
  2891. if((exit_status = initialise_contourenv(contourcnt,contour_halfbands_per_step,dz))<0) // Contour arrays set up here
  2892. return(exit_status);
  2893. }
  2894. return(FINISHED);
  2895. }
  2896. /************************ SET_SPECENV_FRQS ************************
  2897. *
  2898. * FREQWISE BANDS = number of channels for each specenv point
  2899. */
  2900. int set_the_specenv_frqs(int arraycnt,dataptr dz)
  2901. {
  2902. double frqstep, thisfrq, nextfrq;
  2903. int k = 0;
  2904. dz->specenvamp[0] = (float)0.0;
  2905. dz->specenvfrq[0] = (float)1.0;
  2906. dz->specenvpch[0] = (float)log10(dz->specenvfrq[0]);
  2907. dz->specenvtop[0] = (float)dz->halfchwidth;
  2908. frqstep = dz->halfchwidth * (double)dz->formant_bands;
  2909. dz->frq_step = frqstep;
  2910. thisfrq = dz->specenvtop[0];
  2911. k = 1;
  2912. while((nextfrq = thisfrq + frqstep) < dz->nyquist) {
  2913. if(k >= arraycnt) {
  2914. sprintf(errstr,"Formant array too small: set_the_specenv_frqs()\n");
  2915. return(PROGRAM_ERROR);
  2916. }
  2917. dz->specenvfrq[k] = (float)nextfrq;
  2918. dz->specenvpch[k] = (float)log10(dz->specenvfrq[k]);
  2919. dz->specenvtop[k] = (float)min(dz->nyquist,nextfrq);
  2920. thisfrq = nextfrq;
  2921. k++;
  2922. }
  2923. dz->specenvfrq[k] = (float)dz->nyquist;
  2924. dz->specenvpch[k] = (float)log10(dz->nyquist);
  2925. dz->specenvtop[k] = (float)dz->nyquist;
  2926. dz->specenvamp[k] = (float)0.0;
  2927. k++;
  2928. dz->specenvcnt = k;
  2929. dz->infile->specenvcnt = dz->specenvcnt;
  2930. return(FINISHED);
  2931. }
  2932. /**************************** NEW_INNER_LOOP ***************************/
  2933. int new_inner_loop(int windows_in_buf,double *fmax,int passno,int limit,int *inner_lpcnt,double *phase,int *times_index,
  2934. double *target,int *previouspk,int contourcnt,int arp_param,int *up,double minpitch, double maxpitch,dataptr dz)
  2935. {
  2936. int exit_status;
  2937. int wc;
  2938. double totalamp = 0.0;
  2939. for(wc=0; wc<windows_in_buf; wc++) {
  2940. /* TEST *
  2941. if(passno == 2)
  2942. fprintf(stderr,"wc = %d\n",wc);
  2943. * TEST */
  2944. if(dz->total_windows==0) {
  2945. if(passno == FPREANAL && dz->mode != F_SYLABTROF)
  2946. dz->pitches[0] = (float)NOT_PITCH;
  2947. else
  2948. memset((char *)dz->flbufptr[0],0,(size_t)dz->wanted * sizeof(float));
  2949. } else {
  2950. if((exit_status = read_values_from_all_existing_brktables((double)dz->time,dz))<0)
  2951. return(exit_status);
  2952. rectify_window(dz->flbufptr[0],dz);
  2953. switch(passno) {
  2954. case(FPREANAL): // (pass 0)
  2955. if((exit_status = get_totalamp(&totalamp,dz->flbufptr[0],dz->wanted))<0)
  2956. return(exit_status);
  2957. dz->parray[P_PRETOTAMP][dz->total_windows] = totalamp;
  2958. if(dz->mode != F_SYLABTROF) {
  2959. if((exit_status = specpitch(*inner_lpcnt,target,dz))<0)
  2960. return(exit_status);
  2961. }
  2962. break;
  2963. case(FSPECENV): // (pass 1)
  2964. if((exit_status = extract_specenv(0,0,dz))<0)
  2965. return(exit_status);
  2966. switch(dz->mode) {
  2967. case(F_NARROW): // fall thro
  2968. case(F_SQUEEZE): // fall thro
  2969. case(F_INVERT): // fall thro
  2970. case(F_ROTATE): // fall thro
  2971. case(F_SUPPRESS): // fall thro
  2972. case(F_MOVE): // fall thro
  2973. case(F_MOVE2): // fall thro
  2974. case(F_SINUS): // fall thro
  2975. case(F_MAKEFILT): exit_status = get_peaks_and_trofs(*inner_lpcnt,limit,previouspk,dz); break;
  2976. case(F_SEE): exit_status = get_fmax(fmax,dz); break;
  2977. case(F_ARPEG): // fall thro
  2978. case(F_OCTSHIFT): // fall thro
  2979. case(F_TRANS): // fall thro
  2980. case(F_FRQSHIFT): // fall thro
  2981. case(F_RESPACE): // fall thro
  2982. case(F_PINVERT): // fall thro
  2983. case(F_PEXAGG): // fall thro
  2984. case(F_PQUANT): // fall thro
  2985. case(F_PCHRAND): // fall thro
  2986. case(F_RAND): /* Spec colouring doesn't need peak and trof info */ break;
  2987. }
  2988. break;
  2989. case(FPROCESS): // (pass 2)
  2990. if((exit_status = extract_specenv(0,0,dz))<0)
  2991. return(exit_status);
  2992. switch(dz->mode) {
  2993. case(F_NARROW): exit_status = formants_narrow(*inner_lpcnt,dz); break;
  2994. case(F_SQUEEZE): exit_status = formants_squeeze(*inner_lpcnt,dz); break;
  2995. case(F_INVERT): exit_status = formants_invert(*inner_lpcnt,phase,contourcnt,dz); break;
  2996. case(F_ROTATE): exit_status = formants_rotate(*inner_lpcnt,phase,dz); break;
  2997. case(F_SUPPRESS):exit_status = formants_suppress(*inner_lpcnt,dz); break;
  2998. case(F_MOVE2): // fall thro
  2999. case(F_MOVE): exit_status = formants_move(*inner_lpcnt,dz); break;
  3000. case(F_MAKEFILT):exit_status = formants_makefilt(*inner_lpcnt,times_index,dz); break;
  3001. case(F_SEE): exit_status = formants_see(dz); break;
  3002. case(F_NEGATE): exit_status = formants_negate(contourcnt,dz); break;
  3003. case(F_SINUS): exit_status = formants_sinus(*inner_lpcnt,dz); break;
  3004. case(F_ARPEG): // fall thro
  3005. case(F_OCTSHIFT): // fall thro
  3006. case(F_TRANS): // fall thro
  3007. case(F_FRQSHIFT): // fall thro
  3008. case(F_RESPACE): // fall thro
  3009. case(F_PINVERT): // fall thro
  3010. case(F_PEXAGG): // fall thro
  3011. case(F_PQUANT): // fall thro
  3012. case(F_PCHRAND): // fall thro
  3013. case(F_RAND): exit_status = formants_recolor(*inner_lpcnt,phase,up,arp_param,minpitch,maxpitch,contourcnt,dz);break;
  3014. case(F_SEEPKS): exit_status = formants_seepks(dz); break;
  3015. }
  3016. break;
  3017. }
  3018. if(exit_status<0)
  3019. return(exit_status);
  3020. /* TEST *
  3021. fprintf(stderr,"END OF new_inner_loop passno = %d inner_lpcnt = %d of %d\n",passno,*inner_lpcnt,dz->wlength);
  3022. * TEST */
  3023. }
  3024. dz->flbufptr[0] += dz->wanted;
  3025. dz->total_windows++;
  3026. dz->time = (float)(dz->time + dz->frametime);
  3027. (*inner_lpcnt)++;
  3028. }
  3029. return(FINISHED);
  3030. }
  3031. /************************** CHECK_SPECFNU_PARAM_VALIDITY_AND_CONSISTENCY *********************/
  3032. int check_specfnu_param_validity_and_consistency(dataptr dz)
  3033. {
  3034. int exit_status;
  3035. double brkmax = 0.0, brkmin = 0.0;
  3036. if(dz->mode == F_PCHRAND) {
  3037. if(dz->brksize[FPRMAXINT]) {
  3038. if((exit_status = get_maxvalue_in_brktable(&brkmax,FPRMAXINT,dz))<0)
  3039. return exit_status;
  3040. }
  3041. if(dz->param[FPRMAXINT] == 0.0) {
  3042. sprintf(errstr,"RANDOMISATION RANGE IS ZERO: THIS HAS NO EFFECT.\n");
  3043. return DATA_ERROR;
  3044. }
  3045. }
  3046. switch(dz->mode) {
  3047. case(F_SINUS):
  3048. if(dz->vflag[FSIN_FUND])
  3049. dz->fundamental = 1;
  3050. if(dz->vflag[FSIN_EXI])
  3051. dz->retain_unpitched_data_for_deletion = 1;
  3052. break;
  3053. case(F_ROTATE):
  3054. if(dz->brksize[RSPEED]) {
  3055. if((exit_status = get_maxvalue_in_brktable(&brkmax,RSPEED,dz))<0)
  3056. return exit_status;
  3057. }
  3058. if(dz->param[RSPEED] > (double)((int)floor(1.0/dz->frametime))) {
  3059. sprintf(errstr,"ROTATION RATE TOO HIGH FOR THIS ANALYSIS DATA.\n");
  3060. return DATA_ERROR;
  3061. }
  3062. if(dz->vflag[ROTATE_XNH] && dz->vflag[ROTATE_KHM]) {
  3063. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3064. return DATA_ERROR;
  3065. }
  3066. dz->fundamental = 1;
  3067. if(dz->vflag[ROTATE_EXI])
  3068. dz->retain_unpitched_data_for_deletion = 1;
  3069. break;
  3070. case(F_INVERT):
  3071. if(dz->brksize[FVIB]) {
  3072. if((exit_status = get_maxvalue_in_brktable(&brkmax,FVIB,dz))<0)
  3073. return exit_status;
  3074. }
  3075. if(dz->param[FVIB] > (double)((int)floor(1.0/dz->frametime))) {
  3076. sprintf(errstr,"VIBRATO RATE TOO HIGH FOR THIS ANALYSIS DATA.\n");
  3077. return DATA_ERROR;
  3078. }
  3079. if(dz->vflag[INVERT_XNH] && dz->vflag[INVERT_KHM]) {
  3080. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3081. return DATA_ERROR;
  3082. }
  3083. dz->fundamental = 1;
  3084. if(dz->vflag[INVERT_EXI])
  3085. dz->retain_unpitched_data_for_deletion = 1;
  3086. break;
  3087. case(F_PEXAGG): // fall thro
  3088. case(F_PINVERT):
  3089. if(dz->brksize[COLFLT]) {
  3090. if((exit_status = get_minvalue_in_brktable(&brkmin,COLFLT,dz))<0)
  3091. return exit_status;
  3092. if(dz->param[COLFLT] <= 0) {
  3093. sprintf(errstr,"Bottom of range is %d : Enter 0 only as flag (indicates \"use mean pitch of input\")\n",SPEC_MIDIMIN);
  3094. return DATA_ERROR;
  3095. }
  3096. }
  3097. // fall thro
  3098. case(F_PCHRAND): // fall thro
  3099. case(F_PQUANT):
  3100. if(dz->vflag[RECOLOR_DWN] || dz->vflag[RECOLOR_CYC]) {
  3101. if(!dz->brksize[COLRATE] && dz->param[COLRATE] == 0.0) {
  3102. if(dz->vflag[RECOLOR_DWN])
  3103. fprintf(stdout,"WARNING: Downward orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3104. if(dz->vflag[RECOLOR_CYC])
  3105. fprintf(stdout,"WARNING: Cyclic orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3106. fflush(stdout);
  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_ARPEG): // fall thro
  3118. case(F_OCTSHIFT): // fall thro
  3119. case(F_TRANS): // fall thro
  3120. case(F_FRQSHIFT): // fall thro
  3121. case(F_RESPACE): // fall thro
  3122. case(F_RAND):
  3123. if(dz->mode != F_ARPEG) {
  3124. if(dz->vflag[RECOLOR_DWN] || dz->vflag[RECOLOR_CYC]) {
  3125. if(!dz->brksize[COLRATE] && dz->param[COLRATE] == 0.0) {
  3126. if(dz->vflag[RECOLOR_DWN])
  3127. fprintf(stdout,"WARNING: Downward orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3128. if(dz->vflag[RECOLOR_CYC])
  3129. fprintf(stdout,"WARNING: Cyclic orientation of arpeggiation ignored, as there is no arpeggiation set.\n");
  3130. fflush(stdout);
  3131. }
  3132. }
  3133. }
  3134. if(dz->vflag[RECOLOR_DWN] && dz->vflag[RECOLOR_CYC]) {
  3135. sprintf(errstr,"CANNOT ARPEGGIATE SPECTRUM BOTH \"DOWN\" AND \"CYCLICALLY\".\n");
  3136. return DATA_ERROR;
  3137. }
  3138. dz->fundamental = 1;
  3139. if(dz->vflag[RECOLOR_EXI])
  3140. dz->retain_unpitched_data_for_deletion = 1;
  3141. break;
  3142. case(F_SUPPRESS):
  3143. dz->suprflag = 0;
  3144. switch(dz->iparam[SUPRF]) { // Set flags for which formant to suppress
  3145. case(1): dz->suprflag |= 1; break;
  3146. case(2): dz->suprflag |= 2; break;
  3147. case(3): dz->suprflag |= 4; break;
  3148. case(4): dz->suprflag |= 8; break;
  3149. case(12): // fall thro
  3150. case(21): dz->suprflag |= 3; break;
  3151. case(13): // fall thro
  3152. case(31): dz->suprflag |= 5; break;
  3153. case(14): // fall thro
  3154. case(41): dz->suprflag |= 9; break;
  3155. case(23): // fall thro
  3156. case(32): dz->suprflag |= 6; break;
  3157. case(24): // fall thro
  3158. case(42): dz->suprflag |= 10; break;
  3159. case(34): // fall thro
  3160. case(43): dz->suprflag |= 12; break;
  3161. case(123): // fall thro
  3162. case(132): // fall thro
  3163. case(213): // fall thro
  3164. case(231): // fall thro
  3165. case(312): // fall thro
  3166. case(321): dz->suprflag |= 7; break;
  3167. case(124): // fall thro
  3168. case(142): // fall thro
  3169. case(214): // fall thro
  3170. case(241): // fall thro
  3171. case(412): // fall thro
  3172. case(421): dz->suprflag |= 11; break;
  3173. case(134): // fall thro
  3174. case(143): // fall thro
  3175. case(314): // fall thro
  3176. case(341): // fall thro
  3177. case(413): // fall thro
  3178. case(431): dz->suprflag |= 13; break;
  3179. case(234): // fall thro
  3180. case(243): // fall thro
  3181. case(324): // fall thro
  3182. case(342): // fall thro
  3183. case(423): // fall thro
  3184. case(432): dz->suprflag |= 14; break;
  3185. case(1234): // fall thro
  3186. case(1243): // fall thro
  3187. case(1324): // fall thro
  3188. case(1342): // fall thro
  3189. case(1423): // fall thro
  3190. case(1432): // fall thro
  3191. case(2134): // fall thro
  3192. case(2143): // fall thro
  3193. case(2314): // fall thro
  3194. case(2341): // fall thro
  3195. case(2413): // fall thro
  3196. case(2431): // fall thro
  3197. case(3124): // fall thro
  3198. case(3142): // fall thro
  3199. case(3214): // fall thro
  3200. case(3241): // fall thro
  3201. case(3412): // fall thro
  3202. case(3421): // fall thro
  3203. case(4123): // fall thro
  3204. case(4132): // fall thro
  3205. case(4213): // fall thro
  3206. case(4231): // fall thro
  3207. case(4312): // fall thro
  3208. case(4321): dz->suprflag |= 15; break;
  3209. default:
  3210. sprintf(errstr,"Suppress param must \"1\",\"2\",\"3\", or \"4\" or some combo of these, with no repeated items.\n");
  3211. return DATA_ERROR;
  3212. }
  3213. break;
  3214. case(F_NARROW):
  3215. dz->suprflag = 0;
  3216. switch(dz->iparam[NARSUPRES]) {
  3217. case(0): break;
  3218. case(1): dz->suprflag |= 1; break;
  3219. case(2): dz->suprflag |= 2; break;
  3220. case(3): dz->suprflag |= 4; break;
  3221. case(4): dz->suprflag |= 8; break;
  3222. case(12): // fall thro
  3223. case(21): dz->suprflag |= 3; break;
  3224. case(13): // fall thro
  3225. case(31): dz->suprflag |= 5; break;
  3226. case(14): // fall thro
  3227. case(41): dz->suprflag |= 9; break;
  3228. case(23): // fall thro
  3229. case(32): dz->suprflag |= 6; break;
  3230. case(24): // fall thro
  3231. case(42): dz->suprflag |= 10; break;
  3232. case(34): // fall thro
  3233. case(43): dz->suprflag |= 12; break;
  3234. case(123): // fall thro
  3235. case(132): // fall thro
  3236. case(213): // fall thro
  3237. case(231): // fall thro
  3238. case(312): // fall thro
  3239. case(321): dz->suprflag |= 7; break;
  3240. case(124): // fall thro
  3241. case(142): // fall thro
  3242. case(214): // fall thro
  3243. case(241): // fall thro
  3244. case(412): // fall thro
  3245. case(421): dz->suprflag |= 11; break;
  3246. case(134): // fall thro
  3247. case(143): // fall thro
  3248. case(314): // fall thro
  3249. case(341): // fall thro
  3250. case(413): // fall thro
  3251. case(431): dz->suprflag |= 13; break;
  3252. case(234): // fall thro
  3253. case(243): // fall thro
  3254. case(324): // fall thro
  3255. case(342): // fall thro
  3256. case(423): // fall thro
  3257. case(432): dz->suprflag |= 14; break;
  3258. default:
  3259. sprintf(errstr,"Suppress param must \"1\",\"2\",\"3\", or \"4\" or some combo of 3 of these, with no repeated items.\n");
  3260. return DATA_ERROR;
  3261. }
  3262. dz->fundamental = 0;
  3263. if(dz->vflag[NRW_FUND]) {
  3264. if(dz->suprflag & 1) {
  3265. fprintf(stdout,"WARNING: Cannot \"Track Fundamental\" if supressing formants 1: Ignoring.\n");
  3266. fflush(stdout);
  3267. } else
  3268. dz->fundamental = 1;
  3269. }
  3270. if(dz->vflag[NRW_XNH] && dz->vflag[NRW_KHM]) {
  3271. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3272. return DATA_ERROR;
  3273. }
  3274. dz->fundamental = 1;
  3275. if(dz->vflag[NRW_EXI])
  3276. dz->retain_unpitched_data_for_deletion = 1;
  3277. break;
  3278. case(F_MAKEFILT):
  3279. if(dz->vflag[KEEPAMP] && dz->vflag[KEEPINV]) {
  3280. sprintf(errstr,"You cannot use both the peak amplitudes and the peak-amplitude-inverses.\n");
  3281. return DATA_ERROR;
  3282. }
  3283. dz->fundamental = 0;
  3284. if(dz->vflag[FLT_FUND])
  3285. dz->fundamental = 1;
  3286. break;
  3287. case(F_SQUEEZE):
  3288. dz->fundamental = 0;
  3289. if(dz->vflag[SQZ_FUND]) {
  3290. if(dz->vflag[AT_TROFS]) {
  3291. fprintf(stdout,"WARNING: Cannot \"Track Fundamental\" if squeezing around troughs: Ignoring.\n");
  3292. fflush(stdout);
  3293. } else if(dz->iparam[SQZAT] > 1) {
  3294. fprintf(stdout,"WARNING: Cannot \"Track Fundamental\" if not squeezing around 1st formant: Ignoring.\n");
  3295. fflush(stdout);
  3296. } else
  3297. dz->fundamental = 1;
  3298. }
  3299. if(dz->vflag[SQZ_XNH] && dz->vflag[SQZ_KHM]) {
  3300. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3301. return DATA_ERROR;
  3302. }
  3303. dz->fundamental = 1;
  3304. if(dz->vflag[SQZ_EXI])
  3305. dz->retain_unpitched_data_for_deletion = 1;
  3306. break;
  3307. #if 0
  3308. case(F_NEGATE):
  3309. if(dz->vflag[NEG_XNH] && dz->vflag[NEG_KHM]) {
  3310. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3311. return DATA_ERROR;
  3312. }
  3313. if(dz->vflag[NEG_XNH] || dz->vflag[NEG_KHM])
  3314. dz->fundamental = 1;
  3315. if(dz->vflag[NEG_EXI])
  3316. dz->retain_unpitched_data_for_deletion = 1;
  3317. break;
  3318. #endif
  3319. case(F_MOVE):
  3320. if(dz->vflag[MOV_XNH] && dz->vflag[MOV_KHM]) {
  3321. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3322. return DATA_ERROR;
  3323. }
  3324. dz->fundamental = 1;
  3325. if(dz->vflag[MOV_EXI])
  3326. dz->retain_unpitched_data_for_deletion = 1;
  3327. break;
  3328. case(F_MOVE2):
  3329. if(dz->vflag[MOV2_XNH] && dz->vflag[MOV2_KHM]) {
  3330. sprintf(errstr,"SUPPRESS NON-HARMONICS WITH SUPPRESS-HARMONICS WILL PRODUCE ZERO SIGNAL LEVEL.\n");
  3331. return DATA_ERROR;
  3332. }
  3333. dz->fundamental = 1;
  3334. if(dz->vflag[MOV2_EXI])
  3335. dz->retain_unpitched_data_for_deletion = 1;
  3336. break;
  3337. }
  3338. if(dz->fundamental)
  3339. dz->needpitch = 1;
  3340. switch(dz->mode) {
  3341. case(F_OCTSHIFT):// fall thro
  3342. case(F_TRANS): // fall thro
  3343. case(F_FRQSHIFT):// fall thro
  3344. case(F_RESPACE): // fall thro
  3345. case(F_PINVERT): // fall thro
  3346. case(F_PEXAGG): // fall thro
  3347. case(F_PQUANT): // fall thro
  3348. case(F_PCHRAND): // fall thro
  3349. case(F_RAND):
  3350. if(dz->param[COL_LO] >= dz->param[COL_HI]) {
  3351. sprintf(errstr,"Low frq cutoff is >= high frq cutoff. No output will be generated.\n");
  3352. return DATA_ERROR;
  3353. }
  3354. break;
  3355. }
  3356. switch(dz->mode) {
  3357. case(F_PINVERT): // fall thro
  3358. case(F_PEXAGG): // fall thro
  3359. case(F_PQUANT): // fall thro
  3360. case(F_PCHRAND):
  3361. if(dz->param[COLLOPCH] >= dz->param[COLHIPCH]) {
  3362. sprintf(errstr,"Minimum acceptable pitch >= Maximum acceptable pitch. No output will be generated.\n");
  3363. return DATA_ERROR;
  3364. }
  3365. break;
  3366. }
  3367. return FINISHED;
  3368. }
  3369. /************************** FORMANTS_NARROW *********************/
  3370. int formants_narrow(int inner_lpcnt,dataptr dz)
  3371. {
  3372. int exit_status, n, k, thistrof, thispeak, nexttrof, spstt, spend, ccstt, vcstt, ccend = 0, ccendmax, vcend, cc, vc, chdiff, nuchdiff, chomit;
  3373. int zccstt, zccend, zvcstt, newcc, get_fundamental = 0, last_formant_zeroed, top_hno;
  3374. float frqstt, frqend, frq;
  3375. float newfrq, the_fundamental = 0.0;
  3376. double minamp, maxamp, constrict, pre_amptotal = 0.0, post_amptotal = 0.0;
  3377. int flbuf_pktrofs[9];
  3378. int *peakat = dz->iparray[PEAKPOS];
  3379. peakat += inner_lpcnt * PKBLOK;
  3380. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3381. return(exit_status);
  3382. if(dz->fundamental)
  3383. the_fundamental = dz->pitches[inner_lpcnt];
  3384. // FIND THE flbufptr LOCATIONS OF THE PEAKS AND TROFS INDICATED IN THE specevamp ENVELOPE CURVE
  3385. for(n = 0; n < PKBLOK; n+=2) { // Going through the trof and peaks in pairs
  3386. if(dz->fundamental && n == 0)
  3387. get_fundamental = 1;
  3388. thistrof = n;
  3389. thispeak = n+1;
  3390. nexttrof = n+2;
  3391. spstt = peakat[n]; // Get specenvamp locations of a trof.
  3392. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3393. frqstt = 0.0f;
  3394. else
  3395. frqstt = dz->specenvtop[spstt-1];
  3396. frqend = dz->specenvtop[spstt];
  3397. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3398. ccend = (int)ceil(frqend/dz->chwidth);
  3399. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3400. vcstt = ccstt * 2;
  3401. flbuf_pktrofs[thistrof] = ccstt;
  3402. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3403. if(dz->flbufptr[0][AMPP] < minamp) {
  3404. minamp = dz->flbufptr[0][AMPP];
  3405. flbuf_pktrofs[thistrof] = cc;
  3406. }
  3407. }
  3408. zccstt = flbuf_pktrofs[thistrof]; // Remember flbufptr location of trof, for use (if ness) in formant zeroing
  3409. if(n == PKBLOK - 1) // EXIT when final trof sussed.
  3410. break;
  3411. spend = peakat[nexttrof]; // Find specenv location of next TROF
  3412. frqstt = dz->specenvtop[spstt]; // Find the top of the frequency band associated with the lower trof
  3413. frqend = dz->specenvtop[spend - 1]; // Find the bottom of the frequency band associated with the upper trof
  3414. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3415. ccend = (int)ceil(frqend/dz->chwidth);
  3416. maxamp = -HUGE; // Find flbufptr location of PEAK amplitude between the trofs
  3417. vcstt = ccstt * 2;
  3418. flbuf_pktrofs[thispeak] = ccstt;
  3419. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3420. if(dz->flbufptr[0][AMPP] > maxamp) {
  3421. maxamp = dz->flbufptr[0][AMPP];
  3422. flbuf_pktrofs[thispeak] = cc;
  3423. }
  3424. }
  3425. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  3426. if(the_fundamental > 0.0) {
  3427. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  3428. return exit_status;
  3429. flbuf_pktrofs[thispeak] = newcc;
  3430. }
  3431. get_fundamental = 0; // Only (try to) get fundamental when in first formant
  3432. }
  3433. if(dz->suprflag) {
  3434. k = n/2;
  3435. 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
  3436. if(dz->suprflag & k) { // If formant flagged for zeroing
  3437. spend = peakat[nexttrof]; // Find flbufptr location of minamp at NEXT trof
  3438. frqstt = dz->specenvtop[spend-1];
  3439. frqend = dz->specenvtop[spend];
  3440. ccstt = (int)ceil(frqstt/dz->chwidth);
  3441. ccend = (int)ceil(frqend/dz->chwidth);
  3442. minamp = HUGE;
  3443. zccend = ccstt;
  3444. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3445. if(dz->flbufptr[0][AMPP] < minamp) {
  3446. minamp = dz->flbufptr[0][AMPP];
  3447. zccend = cc;
  3448. }
  3449. }
  3450. zvcstt = zccstt * 2; // Zero flbufptr between the 2 trofs
  3451. for(cc = zccstt,vc = zvcstt; cc < zccend; cc++,vc+=2)
  3452. dz->flbufptr[0][AMPP] = 0.0f;
  3453. }
  3454. }
  3455. }
  3456. if(flbuf_pktrofs[0] > 0) { // zero spectrum below initial trof.
  3457. for(cc = 0,vc = 0; cc < flbuf_pktrofs[0]; cc++,vc+=2)
  3458. dz->flbufptr[0][AMPP] = 0.0f;
  3459. }
  3460. ccendmax = 0;
  3461. last_formant_zeroed = 0;
  3462. for(n = 0; n < PKBLOK-1; n++) { // Going through the trof and peaks in pairs
  3463. ccstt = flbuf_pktrofs[n]; // Find flbhfptr trof/peak.
  3464. ccend = flbuf_pktrofs[n+1]; // Find following flbufptr peak/trof.
  3465. if(n == PKBLOK-2)
  3466. ccendmax = ccend;
  3467. if(last_formant_zeroed)
  3468. break;
  3469. chdiff = ccend - ccstt; // Find channel step.
  3470. if(dz->suprflag) {
  3471. if(EVEN(n)) {
  3472. k = n/2;
  3473. k = (int)round(pow(2,k));
  3474. if(dz->suprflag & k) { // If formant zeroed
  3475. if(k == F4_ZEROED) // If last formant zeroed
  3476. last_formant_zeroed = 1; // Don't skip to next trof here as we want to set ccendmax before exiting!!!
  3477. else // but otherwise
  3478. n++; // skip to next trof
  3479. continue;
  3480. }
  3481. }
  3482. }
  3483. nuchdiff = (int)round((double)chdiff * dz->param[NARROWING]);
  3484. chomit = chdiff - nuchdiff; // Reduce it by SQUEEZE and see if any channels are lost
  3485. if(chomit > 0) {
  3486. k = 0; // If they are, zero this number of channels from trof, widening the trof.
  3487. if(EVEN(n)) { // If we're at a trof BEFORE a peak
  3488. while(k < chomit) { // forwardwise
  3489. vc = ccstt * 2;
  3490. dz->flbufptr[0][AMPP] = 0.0f;
  3491. k++;
  3492. ccstt++;
  3493. } // (and forcing trof start to zero).
  3494. } else { // If we're at a trof AFTER a peak
  3495. while(k < chomit) { // backwardswise
  3496. vc = ccend * 2;
  3497. dz->flbufptr[0][AMPP] = 0.0f;
  3498. k++;
  3499. ccend--;
  3500. }
  3501. }
  3502. }
  3503. chdiff = ccend - ccstt; // After possible expansion of trof, calculate new chdiff
  3504. vcstt = ccstt * 2;
  3505. vcend = ccend * 2;
  3506. if(EVEN(n)) { // Trof followed by peak, "splice" upwards: trof (possibly at new location) forced to zero: peak unchanged.
  3507. for(k = 0, cc = ccstt, vc = vcstt; cc < ccend; k++, cc++, vc+=2) {
  3508. constrict = (double)k/(double)chdiff;
  3509. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * constrict);
  3510. }
  3511. } else { // Peak followed by trof, "splice" downwards: trof (possibly at new location) forced to zero: peak unchanged.
  3512. for(k = 0, cc = ccend, vc = vcend; cc > ccstt; k++, cc--, vc-=2) {
  3513. constrict = (double)k/(double)chdiff;
  3514. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * constrict);
  3515. }
  3516. }
  3517. }
  3518. if(dz->vflag[ZEROTOP]) // Zero the remaining upper part of the spectrum (if flagged).
  3519. zero_spectrum_top(ccendmax,dz);
  3520. top_hno = 0;
  3521. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  3522. frq = dz->flbufptr[0][FREQ];
  3523. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3524. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3525. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3526. continue; // zero it
  3527. }
  3528. } else if(dz->vflag[NRW_KHM]) { // If suppressing harmonics
  3529. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3530. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3531. dz->flbufptr[0][AMPP] = 0.0f;
  3532. continue;
  3533. }
  3534. }
  3535. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3536. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3537. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3538. continue;
  3539. }
  3540. }
  3541. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3542. return(exit_status);
  3543. if(post_amptotal > pre_amptotal) {
  3544. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3545. return(exit_status);
  3546. }
  3547. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3548. for(vc=0;vc<dz->wanted;vc+=2)
  3549. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3550. }
  3551. return FINISHED;
  3552. }
  3553. /************************** FORMANTS_SQUEEZE *********************/
  3554. int formants_squeeze(int inner_lpcnt,dataptr dz)
  3555. {
  3556. int exit_status, thistrof, nexttrof, centre, spstt, spend, ccstt, vcstt, ccend, cc, vc, lastcc, locc, hicc, nucc, nuvc, newcc, top_hno, get_fundamental = 0;
  3557. float frqstt, frqend, frq, centrefrq, newfrq, the_fundamental = 0.0;
  3558. double lastamp, minamp, maxamp, frqoffset, nuoffset, nufrq, pre_amptotal = 0.0, post_amptotal = 0.0;
  3559. int *peakat = dz->iparray[PEAKPOS];
  3560. peakat += inner_lpcnt * PKBLOK;
  3561. if(dz->fundamental) {
  3562. get_fundamental = 1;
  3563. the_fundamental = dz->pitches[inner_lpcnt];
  3564. }
  3565. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3566. return(exit_status);
  3567. centre = (dz->iparam[SQZAT] * 2) - 1; // Formants 1,2,3,4 peaks at peaktrof-points 1,3,5,7
  3568. if(dz->vflag[AT_TROFS])
  3569. centre++; // Trofs above them at peaktrof-points 2,4,6,8
  3570. if(dz->vflag[AT_TROFS]) {
  3571. thistrof = centre;
  3572. spstt = peakat[thistrof]; // Get specenvamp locations of a trof.
  3573. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3574. frqstt = 0.0f;
  3575. else
  3576. frqstt = dz->specenvtop[spstt-1];
  3577. frqend = dz->specenvtop[spstt];
  3578. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3579. ccend = (int)ceil(frqend/dz->chwidth);
  3580. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3581. vcstt = ccstt * 2;
  3582. centre = ccstt;
  3583. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3584. if(dz->flbufptr[0][AMPP] < minamp) {
  3585. minamp = dz->flbufptr[0][AMPP];
  3586. centre = cc;
  3587. }
  3588. }
  3589. } else {
  3590. thistrof = centre - 1;
  3591. nexttrof = centre + 1;
  3592. spstt = peakat[thistrof]; // Find specenv location of previous TROF
  3593. spend = peakat[nexttrof]; // Find specenv location of next TROF
  3594. frqstt = dz->specenvtop[spstt]; // Find the top of the frequency band associated with the lower trof
  3595. frqend = dz->specenvtop[spend - 1]; // Find the bottom of the frequency band associated with the upper trof
  3596. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3597. ccend = (int)ceil(frqend/dz->chwidth);
  3598. maxamp = -HUGE; // Find flbufptr location of PEAK amplitude between the trofs
  3599. vcstt = ccstt * 2;
  3600. centre = ccstt;
  3601. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3602. if(dz->flbufptr[0][AMPP] > maxamp) {
  3603. maxamp = dz->flbufptr[0][AMPP];
  3604. centre = cc;
  3605. }
  3606. }
  3607. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  3608. if(the_fundamental > 0.0) {
  3609. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  3610. return exit_status;
  3611. centre = newcc;
  3612. }
  3613. get_fundamental = 0;
  3614. }
  3615. }
  3616. if(dz->xclude_nonh || dz->vflag[SQZ_KHM]) {
  3617. top_hno = 0;
  3618. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  3619. frq = dz->flbufptr[0][FREQ];
  3620. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3621. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3622. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3623. continue; // zero it
  3624. }
  3625. } else if(dz->vflag[SQZ_KHM]) { // If suppressing harmonics
  3626. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3627. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3628. dz->flbufptr[0][AMPP] = 0.0f;
  3629. continue;
  3630. }
  3631. }
  3632. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3633. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3634. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3635. continue;
  3636. }
  3637. }
  3638. }
  3639. vc = centre*2;
  3640. centrefrq = dz->flbufptr[0][FREQ]; // Note the freq at the centre of the shribkage
  3641. lastcc = -1; // Preset variables
  3642. lastamp = -HUGE;
  3643. locc = dz->clength + 1;
  3644. for(cc=0,vc=0;cc<centre;cc++,vc+=2) { // Squeezespectrum below centrefrq
  3645. frqoffset = centrefrq - dz->flbufptr[0][FREQ];
  3646. nuoffset = frqoffset * dz->param[SQZFACT]; // Find the altered frq of this channel, once spectrum squeezed
  3647. nufrq = centrefrq - nuoffset;
  3648. nucc = (int)round(nufrq/dz->chwidth); // Find new channel-location for this frq
  3649. if(nucc < locc)
  3650. locc = nucc; // Note the lowest channel used by squeezed spectrum
  3651. nuvc = nucc * 2;
  3652. if(nucc == lastcc) { // If some other data has already been moved into this channel, keep whichever is the loudest
  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 { // Otherwise, simply move transformed data into this new channel (which may be original chan, just with a frq change)
  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. for(cc=0,vc=0;cc<locc;cc++,vc+=2) // Zero spectrum below squeezed material.
  3665. dz->flbufptr[0][AMPP] = 0.0f;
  3666. cc = centre + 1; // Similar procedure for spectrum above centre
  3667. vc = cc * 2;
  3668. lastcc = -1;
  3669. lastamp = -HUGE;
  3670. hicc = -1;
  3671. for(;cc<dz->clength;cc++,vc+=2) {
  3672. frqoffset = dz->flbufptr[0][FREQ] - centrefrq;
  3673. nuoffset = frqoffset * dz->param[SQZFACT];
  3674. nufrq = centrefrq + nuoffset;
  3675. nucc = (int)round(nufrq/dz->chwidth);
  3676. if(nucc > hicc)
  3677. hicc = nucc; // But new locate the highest channel used by squeezed spectrum
  3678. nuvc = nucc * 2;
  3679. if(nucc == lastcc) {
  3680. if(dz->flbufptr[0][AMPP] > lastamp) {
  3681. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3682. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3683. }
  3684. } else {
  3685. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3686. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3687. }
  3688. lastamp = dz->flbufptr[0][nuvc];
  3689. lastcc = nucc;
  3690. }
  3691. cc = hicc + 1;
  3692. vc = cc * 2;
  3693. for(;cc<dz->clength;cc++,vc+=2) // Zero spectrum above squeezed material.
  3694. dz->flbufptr[0][AMPP] = 0.0f;
  3695. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3696. return(exit_status);
  3697. if(post_amptotal > pre_amptotal) {
  3698. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3699. return(exit_status);
  3700. }
  3701. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3702. for(vc=0;vc<dz->wanted;vc+=2)
  3703. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3704. }
  3705. return FINISHED;
  3706. }
  3707. /************************** FORMANTS_INVERT *********************/
  3708. int formants_invert(int inner_lpcnt,double *phase,int contourcnt,dataptr dz)
  3709. {
  3710. int exit_status, cc, vc, top_hno;
  3711. float the_fundamental;
  3712. double vibpos, frq, specamp, contouramp, diff, pre_amptotal = 0.0, post_amptotal = 0.0;
  3713. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3714. return(exit_status);
  3715. if((exit_status = extract_contour(contourcnt,dz))<0)
  3716. return exit_status;
  3717. top_hno = 0;
  3718. if(dz->xclude_nonh && dz->pitches[inner_lpcnt] < FSPEC_MINFRQ) {
  3719. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2)
  3720. dz->flbufptr[0][AMPP] = 0.0f;
  3721. } else {
  3722. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  3723. frq = (double)dz->flbufptr[0][FREQ];
  3724. the_fundamental = (float)dz->pitches[inner_lpcnt];
  3725. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3726. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,(float)frq,cc,&top_hno,dz)) {
  3727. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3728. continue; // zero it
  3729. }
  3730. } else if(dz->vflag[INVERT_KHM]) { // If suppressing harmonics
  3731. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3732. if(channel_holds_harmonic(the_fundamental,(float)frq,cc,&top_hno,dz)) {
  3733. dz->flbufptr[0][AMPP] = 0.0f;
  3734. continue;
  3735. }
  3736. }
  3737. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3738. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3739. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3740. continue;
  3741. }
  3742. if((exit_status = getspecenvamp(&specamp,frq,0,dz))<0) // Otherwise do spectral inversion
  3743. return(exit_status);
  3744. if((exit_status = getcontouramp(&contouramp,contourcnt,frq,dz))<0)
  3745. return(exit_status);
  3746. diff = specamp - contouramp;
  3747. if(dz->param[FVIB] != 0.0) {
  3748. vibpos = (sin(*phase)); // sin from -1to1
  3749. diff *= vibpos;
  3750. *phase = fmod(*phase + (dz->param[FVIB] * dz->phasefactor),TWOPI);
  3751. } // phase advance depends on current frq ; fmoded to stay within range 0 to 2PI
  3752. dz->flbufptr[0][AMPP] = (float)(max(0.0,contouramp - diff));
  3753. }
  3754. }
  3755. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3756. return(exit_status);
  3757. if(post_amptotal > pre_amptotal) {
  3758. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3759. return(exit_status);
  3760. }
  3761. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3762. for(vc=0;vc<dz->wanted;vc+=2)
  3763. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3764. }
  3765. return FINISHED;
  3766. }
  3767. /************************** FORMANTS_ROTATE *********************/
  3768. int formants_rotate(int inner_lpcnt,double *phase,dataptr dz)
  3769. {
  3770. int exit_status, spstt, spend, ccstt, ccend, vcstt, locc, lovc, hicc, hivc, cc, vc, nucc, nuvc, lastcc, top_hno;
  3771. float frqstt, frqend, lofrq, hifrq, frq, the_fundamental = 0.0;
  3772. double minamp, lastamp, frqdiff, frqstep, nufrq, phasestep, pre_amptotal = 0.0, post_amptotal = 0.0;
  3773. int *peakat = dz->iparray[PEAKPOS];
  3774. peakat += inner_lpcnt * PKBLOK;
  3775. if(dz->fundamental)
  3776. the_fundamental = dz->pitches[inner_lpcnt];
  3777. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3778. return(exit_status);
  3779. spstt = peakat[0];
  3780. spend = peakat[PKBLOK-1];
  3781. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3782. frqstt = 0.0f;
  3783. else
  3784. frqstt = dz->specenvtop[spstt-1];
  3785. frqend = dz->specenvtop[spstt];
  3786. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3787. ccend = (int)ceil(frqend/dz->chwidth);
  3788. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3789. vcstt = ccstt * 2;
  3790. locc = ccstt;
  3791. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3792. if(dz->flbufptr[0][AMPP] < minamp) {
  3793. minamp = dz->flbufptr[0][AMPP];
  3794. locc = cc;
  3795. }
  3796. }
  3797. lovc = locc * 2;
  3798. vc = lovc;
  3799. lofrq = dz->flbufptr[0][FREQ];
  3800. frqstt = dz->specenvtop[spend-1];
  3801. frqend = dz->specenvtop[spend];
  3802. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3803. ccend = (int)ceil(frqend/dz->chwidth);
  3804. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3805. vcstt = ccstt * 2;
  3806. hicc = ccstt;
  3807. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3808. if(dz->flbufptr[0][AMPP] < minamp) {
  3809. minamp = dz->flbufptr[0][AMPP];
  3810. hicc = cc;
  3811. }
  3812. }
  3813. hivc = hicc * 2;
  3814. vc = hivc;
  3815. hifrq = dz->flbufptr[0][FREQ];
  3816. frqdiff = hifrq - lofrq;
  3817. frqstep = (*phase) * frqdiff;
  3818. lastcc = -1;
  3819. lastamp = -HUGE;
  3820. if(dz->xclude_nonh || dz->vflag[ROTATE_KHM]) {
  3821. top_hno = 0;
  3822. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  3823. frq = dz->flbufptr[0][FREQ];
  3824. if(dz->xclude_nonh) { // If excluding non-harmonic data
  3825. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3826. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  3827. continue; // zero it
  3828. }
  3829. } else if(dz->vflag[ROTATE_KHM]) { // If suppressing harmonics
  3830. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  3831. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  3832. dz->flbufptr[0][AMPP] = 0.0f;
  3833. continue;
  3834. }
  3835. }
  3836. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  3837. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  3838. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  3839. continue;
  3840. }
  3841. }
  3842. }
  3843. for(cc = locc, vc = lovc; cc <= hivc; cc++, vc+=2) {
  3844. nufrq = dz->flbufptr[0][FREQ] + frqstep;
  3845. while(nufrq > hifrq) // Keep nufrq within bounds
  3846. nufrq -= frqdiff;
  3847. while(nufrq < lofrq)
  3848. nufrq += frqdiff;
  3849. nucc = (int)round(nufrq/dz->chwidth); // Find new channel-location for this frq
  3850. nuvc = nucc * 2;
  3851. if(nucc == lastcc) { // If some other data has already been moved into this channel, keep whichever is the loudest
  3852. if(dz->flbufptr[0][AMPP] > lastamp) {
  3853. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3854. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3855. }
  3856. } else { // Otherwise, simply move transformed data into this new channel (which may be original chan, just with a frq change)
  3857. dz->flbufptr[0][nuvc] = dz->flbufptr[0][AMPP];
  3858. dz->flbufptr[0][nuvc+1] = (float)nufrq;
  3859. }
  3860. lastamp = dz->flbufptr[0][nuvc];
  3861. lastcc = nucc;
  3862. }
  3863. phasestep = dz->phasefactor * dz->param[RSPEED];
  3864. *phase += phasestep; // Advance phase according to rotation-speed.
  3865. while(*phase > 1.0) // Keep rotation "phase" within 0-1 bounds.
  3866. *phase -= 1.0;
  3867. while(*phase < 0.0)
  3868. *phase += 1.0;
  3869. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3870. return(exit_status);
  3871. if(post_amptotal > pre_amptotal) {
  3872. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3873. return(exit_status);
  3874. }
  3875. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3876. for(vc=0;vc<dz->wanted;vc+=2)
  3877. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3878. }
  3879. return FINISHED;
  3880. }
  3881. /************************** FORMANTS_SUPPRESS *********************/
  3882. int formants_suppress(int inner_lpcnt,dataptr dz)
  3883. {
  3884. int exit_status, n, k, pk, thistrof, nexttrof, spstt, spend, ccstt, vcstt, ccend, pretrof, posttrof, cc ,vc, chandiff;
  3885. float frqstt, frqend;
  3886. double ampdiff, amphere, thisvalue, preminamp, postminamp, thisspecamp, pre_amptotal = 0.0, post_amptotal = 0.0;
  3887. int *peakat = dz->iparray[PEAKPOS];
  3888. peakat += inner_lpcnt * PKBLOK;
  3889. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3890. return(exit_status);
  3891. for(n = 0,pk = 1; n < PKBLOK-1; n+=2,pk *=2) { // Going through the trofs in pairs
  3892. if(dz->suprflag & pk) { // If this formant is to be supressed
  3893. thistrof = n;
  3894. nexttrof = n+2;
  3895. spstt = peakat[thistrof]; // Get specenvamp locations of a trof.
  3896. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  3897. frqstt = 0.0f;
  3898. else
  3899. frqstt = dz->specenvtop[spstt-1];
  3900. frqend = dz->specenvtop[spstt];
  3901. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3902. ccend = (int)ceil(frqend/dz->chwidth);
  3903. preminamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3904. vcstt = ccstt * 2;
  3905. pretrof = ccstt;
  3906. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3907. if(dz->flbufptr[0][AMPP] < preminamp) {
  3908. preminamp = dz->flbufptr[0][AMPP];
  3909. pretrof = cc;
  3910. }
  3911. }
  3912. spend = peakat[nexttrof]; // Get specenvamp locations of next trof.
  3913. frqstt = dz->specenvtop[spend-1];
  3914. frqend = dz->specenvtop[spend];
  3915. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  3916. ccend = (int)ceil(frqend/dz->chwidth);
  3917. postminamp = HUGE; // Find the flbuptr location of minimum amplitude.
  3918. vcstt = ccstt * 2;
  3919. posttrof = ccstt;
  3920. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  3921. if(dz->flbufptr[0][AMPP] < postminamp) {
  3922. postminamp = dz->flbufptr[0][AMPP];
  3923. posttrof = cc;
  3924. }
  3925. }
  3926. ampdiff = postminamp - preminamp;
  3927. chandiff = posttrof - pretrof;
  3928. cc = pretrof + 1; // Scale the intervening channel amps to a linear interp between the 2 trofs
  3929. vc = cc * 2;
  3930. k = 1;
  3931. for(k = 1;k < chandiff;k++,cc++,vc+=2) {
  3932. amphere = ampdiff * ((double)k/(double)chandiff);
  3933. if((exit_status = getspecenvamp(&thisspecamp,(double)dz->flbufptr[0][FREQ],0,dz))<0)
  3934. return(exit_status);
  3935. if(thisspecamp <= 0.0)
  3936. dz->flbufptr[0][AMPP] = 0.0f;
  3937. else {
  3938. if((thisvalue = dz->flbufptr[0][AMPP] * amphere/thisspecamp) < VERY_TINY_VAL)
  3939. dz->flbufptr[0][AMPP] = 0.0f;
  3940. else
  3941. dz->flbufptr[0][AMPP] = (float)thisvalue;
  3942. }
  3943. }
  3944. }
  3945. }
  3946. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  3947. return(exit_status);
  3948. if(post_amptotal > pre_amptotal) {
  3949. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  3950. return(exit_status);
  3951. }
  3952. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  3953. for(vc=0;vc<dz->wanted;vc+=2)
  3954. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  3955. }
  3956. return FINISHED;
  3957. }
  3958. /********************* FORMANTS_SEE *************************/
  3959. int formants_see(dataptr dz)
  3960. {
  3961. int cc,vc, k, blokcnt = SPECFNU_BLOKCNT;
  3962. double thisamp;
  3963. if(dz->specenvcnt * blokcnt >= dz->wanted) {
  3964. sprintf(errstr,"Writing output will overrun buffer.\n");
  3965. return PROGRAM_ERROR;
  3966. }
  3967. blokcnt = 7;
  3968. for(cc=0,vc=0;cc<dz->specenvcnt;cc++,vc+=blokcnt) {
  3969. thisamp = dz->specenvamp[cc];
  3970. for(k=0;k<blokcnt;k++)
  3971. dz->flbufptr[0][vc+k] = (float)thisamp; // Write amplitude vals sequentially, in blocks of 7, for easy viewability
  3972. }
  3973. while(vc<dz->wanted) // Fill up rest of output block with zeros
  3974. dz->flbufptr[0][vc++] = 0.0f;
  3975. return(FINISHED);
  3976. }
  3977. /********************* FORMANTS_SEE *************************/
  3978. int formants_seepks(dataptr dz)
  3979. {
  3980. int n, k, pad, trofcnt = 0, peakcnt = 0, rising = 0, done = 0, vc = 0, localmaxat = 0, localminat = 0;
  3981. double lastamp, localmax, localmin;
  3982. char temp[200], temp2[200];
  3983. temp[0] = ENDOFSTR;
  3984. lastamp = dz->specenvfrq[0];
  3985. for(n=0;n<dz->specenvcnt;n++) {
  3986. switch(n) {
  3987. case(0):
  3988. // thismaxamp = dz->specenvamp[n];
  3989. // thisminamp = dz->specenvamp[n];
  3990. break;
  3991. case(1):
  3992. if(dz->specenvamp[n] > lastamp) {
  3993. sprintf(temp2,"%.1lf",dz->flbufptr[0][vc+1]); // Lowest frq in infile
  3994. pad = 14 - strlen(temp2);
  3995. for(k = 0;k < pad;k++)
  3996. strcat(temp2," ");
  3997. strcat(temp,temp2);
  3998. trofcnt++;
  3999. // thismaxamp = dz->specenvamp[n];
  4000. rising = 1;
  4001. } else {
  4002. // thisminamp = dz->specenvamp[n];
  4003. rising = 0;
  4004. }
  4005. default:
  4006. if(rising) {
  4007. if(dz->specenvamp[n] > lastamp)
  4008. /* thismaxamp = dz->specenvamp[n] */;
  4009. else {
  4010. localmax = -HUGE;
  4011. for(k = 0;k < dz->formant_bands; k++, vc+=2) {
  4012. if(dz->flbufptr[0][AMPP] > localmax) {
  4013. localmax = dz->flbufptr[0][AMPP];
  4014. localmaxat = vc;
  4015. }
  4016. }
  4017. sprintf(temp2,"%.1lf",dz->flbufptr[0][localmaxat+1]);
  4018. pad = 14 - strlen(temp2);
  4019. for(k = 0;k < pad;k++)
  4020. strcat(temp2," ");
  4021. strcat(temp,temp2);
  4022. peakcnt++;
  4023. // thisminamp = dz->specenvamp[n];
  4024. rising = 0;
  4025. }
  4026. } else { // falling
  4027. if(dz->specenvamp[n] < lastamp)
  4028. /* thisminamp = dz->specenvamp[n] */;
  4029. else {
  4030. localmin = HUGE;
  4031. for(k = 0;k < dz->formant_bands; k++, vc+=2) {
  4032. if(dz->flbufptr[0][AMPP] < localmin) {
  4033. localmin = dz->flbufptr[0][AMPP];
  4034. localminat = vc;
  4035. }
  4036. }
  4037. if(trofcnt>0)
  4038. sprintf(temp2,"%.1lf",dz->flbufptr[0][localminat+1]);
  4039. else
  4040. sprintf(temp2,"%.1lf",dz->flbufptr[0][localminat+1]);
  4041. if(++trofcnt == 5) {
  4042. strcat(temp,temp2);
  4043. done = 1;
  4044. } else {
  4045. pad = 14 - strlen(temp2);
  4046. for(k = 0;k < pad;k++)
  4047. strcat(temp2," ");
  4048. strcat(temp,temp2);
  4049. // thisminamp = dz->specenvamp[n];
  4050. rising = 1;
  4051. }
  4052. }
  4053. }
  4054. break;
  4055. }
  4056. if(done)
  4057. break;
  4058. lastamp = dz->specenvamp[n];
  4059. }
  4060. if(trofcnt < 5) {
  4061. if(!dz->warned) {
  4062. fprintf(stdout,"WARNING: At least one window has insufficient peaks (less than 4).\n");
  4063. fprintf(dz->fp,"INSUFFICIENT PEAKS\n");
  4064. dz->warned = 1;
  4065. }
  4066. } else {
  4067. sprintf(temp2,"\n");
  4068. strcat(temp,temp2);
  4069. fprintf(dz->fp,"%s",temp);
  4070. }
  4071. return(FINISHED);
  4072. }
  4073. /********************* FORMANTS_NEGATE *************************/
  4074. int formants_negate(int contourcnt,dataptr dz)
  4075. {
  4076. int exit_status, cc, vc;
  4077. double minamp, maxamp, ampsum, amp, amp2, pre_amptotal = 0.0, post_amptotal = 0.0;
  4078. float frq;
  4079. if((exit_status = extract_contour(contourcnt,dz))<0)
  4080. return exit_status;
  4081. if((exit_status = remember_contouramp(contourcnt,dz))<0)
  4082. return exit_status;
  4083. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  4084. return(exit_status);
  4085. maxamp = -HUGE;
  4086. minamp = HUGE;
  4087. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) { // Find max and min amplitudes of this window
  4088. minamp = min(minamp,dz->flbufptr[0][AMPP]);
  4089. maxamp = max(maxamp,dz->flbufptr[0][AMPP]);
  4090. }
  4091. ampsum = maxamp + minamp;
  4092. 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
  4093. dz->flbufptr[0][AMPP] = (float)ampsum - dz->flbufptr[0][AMPP]; // = max - (X - min) = max + min - X = ampsum - X !!
  4094. if(!dz->vflag[FLATT]) {
  4095. if((exit_status = extract_contour(contourcnt,dz))<0)
  4096. return exit_status;
  4097. for(cc=0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  4098. frq = dz->flbufptr[0][FREQ];
  4099. getcontouramp(&amp,contourcnt,frq,dz); // Contour now
  4100. getcontouramp2(&amp2,contourcnt,frq,dz); // Contour before
  4101. if(amp2 < VERY_TINY_VAL)
  4102. dz->flbufptr[0][AMPP] = 0.0f;
  4103. else
  4104. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * amp/amp2);
  4105. }
  4106. }
  4107. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  4108. return(exit_status);
  4109. if(post_amptotal > pre_amptotal) {
  4110. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  4111. return(exit_status);
  4112. }
  4113. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  4114. for(vc=0;vc<dz->wanted;vc+=2)
  4115. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  4116. }
  4117. return FINISHED;
  4118. }
  4119. /*********************** SPECFNU_PREPROCESS **********************/
  4120. int specfnu_preprocess(dataptr dz)
  4121. {
  4122. int exit_status, n, m;
  4123. dz->warned = 0;
  4124. dz->ischange = 1;
  4125. dz->in_tune = pow(SEMITONE_INTERVAL,WITHIN_RANGE);
  4126. switch(dz->mode) {
  4127. case(F_SEE): // fall thro
  4128. case(F_SEEPKS): // fall thro
  4129. case(F_SYLABTROF): // fall thro
  4130. return FINISHED;
  4131. case(F_ARPEG): // fall thro
  4132. case(F_OCTSHIFT): // fall thro
  4133. case(F_TRANS): // fall thro
  4134. case(F_FRQSHIFT): // fall thro
  4135. case(F_RESPACE): // fall thro
  4136. case(F_PINVERT): // fall thro
  4137. case(F_PEXAGG): // fall thro
  4138. case(F_PQUANT): // fall thro
  4139. case(F_PCHRAND): // fall thro
  4140. case(F_RAND):
  4141. dz->phasefactor = dz->frametime; // Arpeggiation sweeps 0 & 1
  4142. if((dz->iparray[ISHARM] = (int *)malloc(dz->clength * sizeof(int)))==NULL) {
  4143. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonics markers.\n");
  4144. return(MEMORY_ERROR);
  4145. }
  4146. return FINISHED;
  4147. case(F_NARROW): // Narrowing by 10 shrinks formantsize to 1/10
  4148. if(dz->brksize[NARROWING]) {
  4149. for(n=0,m=1;n<dz->brksize[NARROWING];n++,m+=2)
  4150. dz->brk[NARROWING][m] = 1.0/dz->brk[NARROWING][m];
  4151. } else
  4152. dz->param[NARROWING] = 1.0/dz->param[NARROWING];
  4153. dz->warned = 0;
  4154. break;
  4155. case(F_SQUEEZE): // Squeeze by 10 shrinks spectrum by 1/10
  4156. if(dz->brksize[SQZFACT]) {
  4157. for(n=0,m=1;n<dz->brksize[SQZFACT];n++,m+=2)
  4158. dz->brk[SQZFACT][m] = 1.0/dz->brk[SQZFACT][m];
  4159. } else
  4160. dz->param[SQZFACT] = 1.0/dz->param[SQZFACT];
  4161. dz->warned = 0;
  4162. break;
  4163. case(F_INVERT): // Variation is sinusoidal
  4164. dz->phasefactor = TWOPI * dz->frametime;// At 1Hz, we advance 2PI in 1 sec, so we advance 2PI * frametime in frametime-secs
  4165. break; // At 10Hz,we advance 2PI * 10 in 1 sec, so we advance 2PI * 10 * frametime in frametime-secs
  4166. case(F_ROTATE): // Variation sweeps through formants range from "0" to "1"
  4167. dz->phasefactor = dz->frametime; // At 1Hz, we advance by 1 in 1 sec, so we advance 1 * frametime in frametime-secs
  4168. break; // At 10Hz,we advance 10 in 1 sec, so we advance 10 * frametime in frametime-secs
  4169. case(F_MAKEFILT): // Creates array to store pitches to use in filter
  4170. if((dz->parray[FILTPICH] = (double *)malloc(dz->iparam[FPKCNT] * 4 * dz->timeblokcnt * sizeof(double)))==NULL) {
  4171. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitches data.\n");
  4172. return(MEMORY_ERROR);
  4173. }
  4174. if((dz->parray[FILTAMP] = (double *)malloc(dz->iparam[FPKCNT] * 4 * dz->timeblokcnt * sizeof(double)))==NULL) {
  4175. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Amps data.\n");
  4176. return(MEMORY_ERROR);
  4177. }
  4178. if((dz->parray[LOCALPCH] = (double *)malloc(dz->iparam[FPKCNT] * 4 * sizeof(double)))==NULL) {
  4179. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitches data.\n");
  4180. return(MEMORY_ERROR);
  4181. }
  4182. if((dz->parray[LOCALAMP] = (double *)malloc(dz->iparam[FPKCNT] * 4 * sizeof(double)))==NULL) {
  4183. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Amps data.\n");
  4184. return(MEMORY_ERROR);
  4185. }
  4186. break;
  4187. case(F_MOVE):
  4188. case(F_MOVE2):
  4189. for(n = FAMP1; n < PKSARRAYCNT; n++) {
  4190. if((dz->fptr[n] = (float *)malloc(dz->specenvcnt * sizeof(float)))==NULL) {
  4191. sprintf(errstr,"INSUFFICIENT MEMORY to store Intermediate formant data %d.\n",n+1);
  4192. return(MEMORY_ERROR);
  4193. }
  4194. }
  4195. for(n = FMULT;n < PRE_P_ARRAYCNT; n++) {
  4196. if((dz->parray[n] = (double *)malloc(dz->clength * sizeof(double)))==NULL) {
  4197. sprintf(errstr,"INSUFFICIENT MEMORY to store Intermediate formant double-data, item %d.\n",n+1);
  4198. return(MEMORY_ERROR);
  4199. }
  4200. }
  4201. if((dz->iparray[FCNT] = (int *)malloc(5 * sizeof(int)))==NULL) {
  4202. sprintf(errstr,"INSUFFICIENT MEMORY to store Intermediate dformant array data counts.\n");
  4203. return(MEMORY_ERROR);
  4204. }
  4205. dz->ischange = 0;
  4206. break;
  4207. case(F_SINUS):
  4208. for(n=0,m = FOR_FRQ1;n < P_SINUS_ARRAYS; n++,m++) {
  4209. if((dz->fptr[m] = (float *)malloc(dz->wlength * sizeof(float)))==NULL) { // 4 arrays store pitch-tracks of 4 formants
  4210. sprintf(errstr,"INSUFFICIENT MEMORY to store Formant %d pitch-tracks.\n",n+1); // 4 more arrays store smoothed or quantised tracks
  4211. return(MEMORY_ERROR); // & (later) related transposition values
  4212. }
  4213. }
  4214. for(n=0,m = F_CHTRAIN1;n < 9; n++,m++) { // 4 arrays store the (original) chanpositions
  4215. if((dz->iparray[m] = (int *)malloc(dz->wlength * sizeof(int)))==NULL) { // of the formant peakfrqs
  4216. sprintf(errstr,"INSUFFICIENT MEMORY to store Formant %d pitch-tracks.\n",n+1);
  4217. return(MEMORY_ERROR);
  4218. }
  4219. }
  4220. break;
  4221. }
  4222. if((exit_status = initialise_specenv2(dz)) < 0)
  4223. return exit_status;
  4224. if(dz->mode == F_NEGATE)
  4225. return FINISHED;
  4226. if((exit_status = initialise_peakstore(dz)) < 0)
  4227. return exit_status;
  4228. dz->pktrofcnt = PKBLOK; // We start counting aFTER 1 block of peaks, as window 1 has no PEAK info
  4229. dz->badpks = 0;
  4230. dz->zeroset = 0;
  4231. return FINISHED;
  4232. }
  4233. /*********************** GET_PEAKS_AND_TROFS **********************/
  4234. int get_peaks_and_trofs(int inner_lpcnt,int limit,int *previouspk,dataptr dz)
  4235. {
  4236. int exit_status, n, i, j, k, there, valid, rising = 0, done = 0;
  4237. int abscnt = dz->pktrofcnt, localcnt = 0, blokstep, ilpcnt;
  4238. float lastamp = 0.0;
  4239. double interp;
  4240. float *peaktrof = dz->fptr[PKTROF];
  4241. int *pos = dz->iparray[PEAKPOS];
  4242. float *pkdiff = dz->fptr[PKDIFF];
  4243. for(n=0;n<dz->specenvcnt;n++) {
  4244. switch(n) {
  4245. case(0):
  4246. break;
  4247. case(1):
  4248. if(dz->specenvamp[n] > lastamp) {
  4249. peaktrof[abscnt] = lastamp;
  4250. pos[abscnt] = n-1;
  4251. abscnt++;
  4252. localcnt++;
  4253. rising = 1;
  4254. } else
  4255. rising = 0;
  4256. break;
  4257. default:
  4258. if(rising) {
  4259. if(dz->specenvamp[n] < lastamp) {
  4260. peaktrof[abscnt] = lastamp;
  4261. pos[abscnt] = n-1;
  4262. abscnt++;
  4263. localcnt++;
  4264. rising = 0;
  4265. }
  4266. } else { // falling
  4267. if(dz->specenvamp[n] > lastamp) {
  4268. peaktrof[abscnt] = lastamp;
  4269. pos[abscnt] = n-1;
  4270. abscnt++;
  4271. localcnt++;
  4272. if(localcnt == PKBLOK) // 5 trofs and 4 peaks
  4273. done = 1;
  4274. else
  4275. rising = 1;
  4276. }
  4277. }
  4278. break;
  4279. }
  4280. if(done)
  4281. break;
  4282. lastamp = dz->specenvamp[n];
  4283. }
  4284. if(!done) {
  4285. dz->badpks = 1;
  4286. dz->pktrofcnt += PKBLOK;
  4287. if(dz->pktrofcnt >= limit) { // If we're at LAST window, and there are bad blocks, forwardfill with last valid vals
  4288. if(*previouspk < 0) {
  4289. sprintf(errstr,"No window has (the required) 4 peaks.\n");
  4290. return DATA_ERROR;
  4291. }
  4292. for(k = *previouspk + PKBLOK ;k < dz->pktrofcnt; k += PKBLOK) {
  4293. for(j = 0,there = k, valid = *previouspk; j < PKBLOK; j++,there++,valid++)
  4294. peaktrof[there] = peaktrof[valid];
  4295. if(dz->mode == F_SINUS) {
  4296. ilpcnt = k/PKBLOK;
  4297. if((exit_status = store_formant_frq_data(ilpcnt,dz))<0)
  4298. return (exit_status);
  4299. }
  4300. }
  4301. return FINISHED;
  4302. }
  4303. }
  4304. else {
  4305. if(dz->badpks) {
  4306. if(*previouspk < 0) { // Backfill non-peak bloks at start with same vals as 1st true peakblok found
  4307. for(k = 0;k < dz->pktrofcnt; k += PKBLOK) {
  4308. for(j = 0,there = k, valid = dz->pktrofcnt; j < PKBLOK; j++,there++,valid++)
  4309. peaktrof[there] = peaktrof[valid];
  4310. if(dz->mode == F_SINUS) {
  4311. ilpcnt = k/PKBLOK;
  4312. if((exit_status = store_formant_frq_data(ilpcnt,dz))<0)
  4313. return (exit_status);
  4314. }
  4315. }
  4316. } else { // Or infill non-peak bloks with interp of existing peakbloks
  4317. for(j = 0;j < PKBLOK; j++) // Get differences between peak and trogfs vals in the 2 valid pkbloks
  4318. pkdiff[j] = (float)(peaktrof[dz->pktrofcnt + j] - peaktrof[*previouspk + j]);
  4319. blokstep = (dz->pktrofcnt - *previouspk)/PKBLOK; // Find number of bad blocks
  4320. for(k = *previouspk + PKBLOK, i = 1;k < dz->pktrofcnt; k += PKBLOK, i++) {
  4321. interp = (double)i/(double)blokstep; // Set interp porportion
  4322. for(j = 0,there = k; j < PKBLOK; j++,there++) // Write in interpd values
  4323. peaktrof[there] = (float)(peaktrof[*previouspk + k] + (pkdiff[j] * interp));
  4324. }
  4325. }
  4326. dz->badpks = 0;
  4327. }
  4328. *previouspk = dz->pktrofcnt;
  4329. if(dz->mode == F_SINUS) {
  4330. if((exit_status = store_formant_frq_data(inner_lpcnt,dz))<0)
  4331. return (exit_status);
  4332. }
  4333. dz->pktrofcnt += PKBLOK;
  4334. if(dz->pktrofcnt >= limit)
  4335. return FINISHED;
  4336. }
  4337. return CONTINUE;
  4338. }
  4339. /****************************************** INITIALISE_PEAKSTORE ************************************/
  4340. int initialise_peakstore(dataptr dz)
  4341. {
  4342. if((dz->fptr[PKTROF] = (float *)malloc((dz->wlength + 2) * PKBLOK * sizeof(float)))==NULL) { // +2 = SAFETY
  4343. sprintf(errstr,"INSUFFICIENT MEMORY for store of window peaks and troughs(2).\n");
  4344. return(MEMORY_ERROR);
  4345. }
  4346. if((dz->fptr[PKDIFF] = (float *)malloc(PKBLOK * sizeof(float)))==NULL) {
  4347. sprintf(errstr,"INSUFFICIENT MEMORY for store of differences between window peaks and troughs.\n");
  4348. return(MEMORY_ERROR);
  4349. }
  4350. if((dz->iparray[PEAKPOS] = (int *)malloc(dz->wlength * PKBLOK * sizeof(int)))==NULL) {
  4351. sprintf(errstr,"INSUFFICIENT MEMORY for store of locations of peaks and troughs(2).\n");
  4352. return(MEMORY_ERROR);
  4353. }
  4354. return FINISHED;
  4355. }
  4356. /************************** GET_FMAX ***********************/
  4357. int get_fmax(double *fmax,dataptr dz)
  4358. {
  4359. int n;
  4360. for(n = 0; n < dz->specenvcnt;n++)
  4361. *fmax = max(dz->specenvamp[n],*fmax);
  4362. return FINISHED;
  4363. }
  4364. /**************************** HANDLE_THE_MAKEFILT_SPECIAL_DATA ****************************/
  4365. int handle_the_makefilt_special_data(char *str,dataptr dz)
  4366. {
  4367. int is_hs = -1, is_pitches = 0, is_scale = 0, is_elacs = 0, scale_division = 12, ignore_further_times = 0;
  4368. int cnttimes = 0, cntpitches = 0, linecnt, pitchpos, oct1pitchpos, step, n, m,k, offset, done, mindiffat, nubincnt, timepos, trueoct_cnt;
  4369. double dummy = 0.0, reference_pitch = 60.0, lasttime = 0.0, ratio, octstep, nextpitch, mindiff, thisdiff, nupitch;
  4370. double pseudoct_size = 12.0, semitone_len, thispitch, octfoot = 0.0;
  4371. FILE *fp;
  4372. double *prepitch = NULL, *binpitch = NULL, *bintop = NULL;
  4373. int arraysize, *ftime;
  4374. char temp[800], *p;
  4375. if((fp = fopen(str,"r"))==NULL) {
  4376. sprintf(errstr,"Cannot open file %s to read data.\n",str);
  4377. return(DATA_ERROR);
  4378. }
  4379. linecnt = 0;
  4380. while(fgets(temp,200,fp)!=NULL) {
  4381. p = temp;
  4382. while(isspace(*p))
  4383. p++;
  4384. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  4385. continue;
  4386. if(*p == '#') { // Look for #HF, #HS, or #SCALES marker
  4387. if(cnttimes == 0) {
  4388. sprintf(errstr,"No time segmentation specified in file %s.\n",str);
  4389. return(DATA_ERROR);
  4390. }
  4391. if(strncmp(p,"#HS",3) == 0) {
  4392. is_hs = 1;
  4393. is_pitches = 1;
  4394. } else if(strncmp(p,"#HF",3) == 0) {
  4395. is_hs = 0;
  4396. is_pitches = 1;
  4397. } else if(strncmp(p,"#SCALE",6) == 0) {
  4398. is_hs = 0;
  4399. is_scale = 1;
  4400. is_pitches = 1;
  4401. } else if(strncmp(p,"#ELACS",6) == 0) {
  4402. is_hs = 0;
  4403. is_elacs = 1;
  4404. is_pitches = 1;
  4405. }
  4406. else {
  4407. // sprintf(errstr,"Invalid Field, Set, or Scale marker (%d) on line %d in file %s\n",linecnt+1,p,str);
  4408. //RWD I think it is meant to say this:
  4409. sprintf(errstr,"Invalid Field, Set, or Scale marker (%s) on line %d in file %s\n",p,linecnt+1,str);
  4410. return(DATA_ERROR);
  4411. }
  4412. } else {
  4413. while(get_float_from_within_string(&p,&dummy)) {
  4414. if(is_pitches) {
  4415. if(is_scale) { // For scales, we need to find note-per-oct and ref-pitch
  4416. switch(cntpitches) {
  4417. case(0):
  4418. if(dummy < 1 || dummy > MAXSCALECNT) {
  4419. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4420. return(DATA_ERROR);
  4421. }
  4422. scale_division = (int)round(dummy);
  4423. break;
  4424. case(1):
  4425. if(dummy < 0 || dummy > MIDIMAX) {
  4426. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4427. return(DATA_ERROR);
  4428. }
  4429. reference_pitch = dummy;
  4430. break;
  4431. default:
  4432. sprintf(errstr,"Too many vals specified for scale in file %s: need only notes-per-octave and (MIDI)ref-pitch.\n",str);
  4433. return(DATA_ERROR);
  4434. }
  4435. } else if(is_elacs) { // For elacs, we need to find "octave"-size,note-per-oct and ref-pitch
  4436. switch(cntpitches) {
  4437. case(0):
  4438. if(dummy < PSEUDOCTMIN || dummy > PSEUDOCTMAX) {
  4439. sprintf(errstr,"\"Octave\" size (%d) at line %d out of range (%d to %d)\n",(int)round(dummy),linecnt+1,PSEUDOCTMIN,PSEUDOCTMAX);
  4440. return(DATA_ERROR);
  4441. }
  4442. pseudoct_size = (int)round(dummy);
  4443. break;
  4444. case(1):
  4445. if(dummy < 1 || dummy > MAXSCALECNT) {
  4446. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4447. return(DATA_ERROR);
  4448. }
  4449. scale_division = (int)round(dummy);
  4450. if((double)pseudoct_size/(double)scale_division < .01) {
  4451. sprintf(errstr,"Scale steps per true octave (%.lf) too small (Minimum %.2lf)\n",(double)pseudoct_size/(double)scale_division,0.01);
  4452. return(DATA_ERROR);
  4453. }
  4454. break;
  4455. case(2):
  4456. if(dummy < 0 || dummy > MIDIMAX) {
  4457. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4458. return(DATA_ERROR);
  4459. }
  4460. reference_pitch = dummy;
  4461. break;
  4462. default:
  4463. sprintf(errstr,"Too many vals for escal in file %s: need only \"oct\"-size, notes-per-\"oct\" and (MIDI)ref-pitch.\n",str);
  4464. return(DATA_ERROR);
  4465. }
  4466. } else { // For HS or HF we need a set of MIDI values
  4467. if(dummy < 0 || dummy > MIDIMAX) {
  4468. sprintf(errstr,"Invalid pitch data (%lf) at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4469. return(DATA_ERROR);
  4470. }
  4471. }
  4472. cntpitches++;
  4473. } else {
  4474. if(ignore_further_times) // If ignoring times, keep reading till we reach HF/HS data
  4475. continue;
  4476. if(cnttimes == 0.0) {
  4477. if(dummy < 0) {
  4478. sprintf(errstr,"Invalid time (%lf) at line %d in file %s.\n",dummy,linecnt+1,str);
  4479. return(DATA_ERROR);
  4480. } // If 1st time val at or after file end, Ignore it and further time-values
  4481. if(dummy >= dz->duration) {
  4482. fprintf(stdout,"WARNING: First time (%lf) at or beyond file end (%lf): will use unsegmented src.\n",dummy,dz->duration);
  4483. fflush(stdout);
  4484. ignore_further_times = 1;
  4485. }
  4486. } else { // Ensure time-markers increase
  4487. if (dummy <= lasttime) {
  4488. sprintf(errstr,"Times do not advance (%lf to %lf) at from line %d to line %d\n",lasttime,dummy,linecnt,linecnt+1);
  4489. return(DATA_ERROR);
  4490. } // Ignore any time markers at or after file end
  4491. if(dummy >= dz->duration) {
  4492. 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);
  4493. fflush(stdout);
  4494. cnttimes--; // Counters the increment in "cnttimes" below
  4495. ignore_further_times = 1;
  4496. }
  4497. }
  4498. lasttime = dummy;
  4499. cnttimes++;
  4500. }
  4501. }
  4502. }
  4503. }
  4504. if(cnttimes == 0) { // Should be redundant
  4505. sprintf(errstr,"No time-segmentation specified, in file %s.\n",str);
  4506. return(DATA_ERROR);
  4507. }
  4508. if(is_hs == -1) {
  4509. sprintf(errstr,"No data for Harmonic-Field, Harmonic-Set or Scale-type specified in file %s.\n",str);
  4510. return(DATA_ERROR);
  4511. }
  4512. if(is_scale || is_elacs) {
  4513. if(is_scale) {
  4514. arraysize = (scale_division * MIDIOCTSPAN) + 1;
  4515. if((dz->parray[PBINPCH] = (double *)malloc(arraysize * 4 * sizeof(double)))==NULL) {
  4516. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4517. return(MEMORY_ERROR);
  4518. }
  4519. binpitch = dz->parray[PBINPCH];
  4520. pitchpos = 0; // Dummy entry in position [0] - (allows pitchtop counter to tally with pitch centre conter)
  4521. binpitch[pitchpos++] = 0.0;
  4522. // SPECIFY PITCHES IN 1ST 8VA
  4523. switch(scale_division) {
  4524. case(1):// fall thro // For rational divisors of 12
  4525. case(2):// fall thro
  4526. case(3):// fall thro
  4527. case(4):// fall thro
  4528. case(6):// fall thro
  4529. case(12):
  4530. step = (int)round(SEMITONES_PER_OCTAVE)/scale_division;
  4531. for(n = 0;n < scale_division;n+=step)
  4532. binpitch[pitchpos++] = (double)n;
  4533. break;
  4534. default: // Otherwise
  4535. for(n = 0;n < scale_division;n++) {
  4536. ratio = (double)n/(double)scale_division;
  4537. binpitch[pitchpos++] = SEMITONES_PER_OCTAVE * ratio;
  4538. }
  4539. break;
  4540. }
  4541. // SPECIFY PITCHES IN ALL OTHER 8VAs
  4542. done = 0;
  4543. octstep = 0;
  4544. for(m=1;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  4545. oct1pitchpos = 1; // Point to vals in lowest 8va
  4546. octstep += SEMITONES_PER_OCTAVE;
  4547. for(n=0;n<scale_division;n++) { // Copy these, N octaves higher, into higher octaves
  4548. nextpitch = binpitch[oct1pitchpos++] + octstep;
  4549. if(nextpitch > MIDIMAX) {
  4550. done = 1;
  4551. break;
  4552. }
  4553. binpitch[pitchpos++] = nextpitch;
  4554. }
  4555. if(done)
  4556. break;
  4557. }
  4558. dz->bincnt = pitchpos; // Remember how many bins we have
  4559. } else { // is_elacs
  4560. arraysize = 0;
  4561. trueoct_cnt = 0;
  4562. semitone_len = 0;
  4563. while(trueoct_cnt < MIDIOCTSPAN) {
  4564. arraysize += scale_division;
  4565. semitone_len += pseudoct_size;
  4566. trueoct_cnt = (int)floor(semitone_len/SEMITONES_PER_OCTAVE);
  4567. }
  4568. if((dz->parray[PBINPCH] = (double *)malloc(arraysize * 4 * sizeof(double)))==NULL) {
  4569. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4570. return(MEMORY_ERROR);
  4571. }
  4572. binpitch = dz->parray[PBINPCH];
  4573. pitchpos = 0; // Dummy entry in position [0] - (allows pitchtop counter to tally with pitch centre conter)
  4574. binpitch[pitchpos++] = 0.0;
  4575. // SPECIFY PITCHES IN EACH pseudo8va Ffor all pseudo8vas until MIDIMAX is reached
  4576. thispitch = 0.0;
  4577. octfoot = 0.0;
  4578. while(thispitch <= MIDIMAX) {
  4579. for(n = 0;n < scale_division;n++) {
  4580. ratio = (double)n/(double)scale_division;
  4581. if((thispitch = (pseudoct_size * ratio) + octfoot) > MIDIMAX) {
  4582. break;
  4583. }
  4584. binpitch[pitchpos++] = thispitch;
  4585. }
  4586. octfoot += pseudoct_size;
  4587. }
  4588. dz->bincnt = pitchpos; // Remember how many bins we have
  4589. }
  4590. if(is_elacs || !flteq(fmod(reference_pitch,SEMITONES_PER_OCTAVE),0.0)) { // Either, is_elacs, so pitches not guaranteed to include reference_pitch
  4591. // OR, Reference-pitch is not at multiple of 12
  4592. // Find pitch closest to reference pitch, and find interval distance to ref-pitch
  4593. mindiff = HUGE;
  4594. mindiffat = 0;
  4595. for(n = 1; n < dz->bincnt; n++) { // binpitch[0] is a dummy
  4596. thisdiff = fabs(reference_pitch - binpitch[n]);
  4597. if(thisdiff < mindiff) {
  4598. mindiff = thisdiff;
  4599. mindiffat = n;
  4600. }
  4601. }
  4602. // Now transpose set so it includes ref-pitch
  4603. mindiff = reference_pitch - binpitch[mindiffat];
  4604. if(mindiff > 0.0) {
  4605. for(n = 1; n < dz->bincnt; n++) {
  4606. nupitch = binpitch[n] + mindiff;
  4607. if(nupitch > 127)
  4608. break;
  4609. binpitch[n] = nupitch;
  4610. }
  4611. dz->bincnt = n; // May be smaller than orig, if binpitch pushed eyond 127
  4612. } else if(mindiff < 0.0) {
  4613. nubincnt = 1;
  4614. for(n = 1; n < dz->bincnt; n++) {
  4615. nupitch = binpitch[n] + mindiff;
  4616. if(nupitch >= 0.0) // binpitch now below zero are ignored, so the new bincnt (m) does not increment
  4617. binpitch[nubincnt++] = nupitch; // Otherwise new binpitch are written over orig binpitch (possibly lower in array - but never higher!!)
  4618. }
  4619. dz->bincnt = nubincnt;
  4620. }
  4621. }
  4622. if((dz->iparray[PCNTBIN] = (int *)malloc(dz->bincnt * 4 * sizeof(int)))==NULL) {
  4623. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Counting Data.\n");
  4624. return(MEMORY_ERROR);
  4625. }
  4626. if((dz->parray[PBINTOP] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  4627. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Top Data.\n");
  4628. return(MEMORY_ERROR);
  4629. }
  4630. if((dz->parray[PBINAMP] = (double *)malloc(dz->bincnt * 4 * sizeof(double)))==NULL) {
  4631. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Amp Data.\n");
  4632. return(MEMORY_ERROR);
  4633. }
  4634. } else {
  4635. // If not scale: create array to store pitchdata initially read from file
  4636. if((dz->parray[PREPICH] = (double *)malloc((cntpitches + 1) * sizeof(double)))==NULL) {
  4637. sprintf(errstr,"INSUFFICIENT MEMORY to store Initial Filter Pitch Data.\n");
  4638. return(MEMORY_ERROR);
  4639. }
  4640. prepitch = dz->parray[PREPICH];
  4641. }
  4642. arraysize = cnttimes;
  4643. arraysize+=2; // Need (possibly) to insert time at 0.0, and at end;
  4644. if((dz->lparray[FTIMES] = (int *)malloc(arraysize * sizeof(int)))==NULL) {
  4645. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter Times Data.(2)\n");
  4646. return(MEMORY_ERROR);
  4647. }
  4648. ftime = dz->lparray[FTIMES];
  4649. timepos = 0;
  4650. ftime[timepos++] = 0;
  4651. rewind(fp);
  4652. is_pitches = 0;
  4653. linecnt = 0;
  4654. cntpitches = 0;
  4655. while(fgets(temp,200,fp)!=NULL) {
  4656. p = temp;
  4657. while(isspace(*p))
  4658. p++;
  4659. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  4660. continue;
  4661. if(*p == '#') {
  4662. if(is_scale) // If HF/HS data is a scale, we already have the pitch data: so quit
  4663. break;
  4664. is_pitches = 1;
  4665. continue;
  4666. } else {
  4667. while(get_float_from_within_string(&p,&dummy)) {
  4668. if(is_pitches)
  4669. prepitch[cntpitches++] = dummy;
  4670. else {
  4671. if(ignore_further_times)
  4672. continue;
  4673. if(dummy >= dz->duration) {
  4674. ignore_further_times = 1; // Defaults to the zero val already in array
  4675. continue;
  4676. }
  4677. if(timepos == 1 && flteq(dummy,0.0))
  4678. continue; // Already got time zero in times array, but may be other times to store
  4679. ftime[timepos++] = (int)round(dummy/dz->frametime);
  4680. }
  4681. }
  4682. }
  4683. }
  4684. if(ftime[timepos-1] > dz->wlength - MINWINDOWS) // If last time very close to endoffile
  4685. ftime[timepos-1] = dz->wlength + 1; // move it to AFTER end of file
  4686. else { // If not, add another point AFTER end of file
  4687. ftime[timepos] = dz->wlength + 1;
  4688. timepos++;
  4689. }
  4690. 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
  4691. fclose(fp);
  4692. if(!is_scale) {
  4693. dz->itemcnt = cntpitches;
  4694. dz->itemcnt = sort_pitches(dz); // Some pitches may be duplicated: they also need to be in ascending order
  4695. if(is_hs)
  4696. dz->bincnt = dz->itemcnt + 1; // Space for all entered pitches + dummy value at [0]
  4697. else {
  4698. for(n = 0;n < dz->itemcnt; n++) { // For HF, duplicate pitches over all 8vas
  4699. while(prepitch[n] > 0.0)
  4700. prepitch[n] -= SEMITONES_PER_OCTAVE; // 1st transpose all pitches into lowest octave
  4701. prepitch[n] += SEMITONES_PER_OCTAVE;
  4702. }
  4703. dz->itemcnt = sort_pitches(dz); // After transposition, some pitches may be duplicated
  4704. dz->bincnt = (dz->itemcnt * MIDIOCTSPAN) + 1; // pitches are to be duplicated in all 8vas + we need the dummy val at [0]
  4705. }
  4706. if((dz->parray[PBINPCH] = (double *)malloc(dz->bincnt * 4 * sizeof(double)))==NULL) {
  4707. sprintf(errstr,"INSUFFICIENT MEMORY to store Pitch-Bin-Top data.\n");
  4708. return(MEMORY_ERROR);
  4709. }
  4710. binpitch = dz->parray[PBINPCH];
  4711. if(is_hs) { // For HS, merely copy pitches into final array, leaving dummy value at [0]
  4712. memcpy((char *)(dz->parray[PBINPCH] + 1),(char *)dz->parray[PREPICH],(dz->bincnt - 1) * sizeof(double));
  4713. dz->parray[PBINPCH][0] = 0.0;
  4714. } else { // For HF, copy pitches into all 8vas in MIDI range
  4715. done = 0;
  4716. pitchpos = 0;
  4717. binpitch[pitchpos++] = 0.0; // Leave dummy value at zero
  4718. octstep = 0;
  4719. for(m=0;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  4720. for(n=0;n<dz->itemcnt;n++) { // Copy pitches in lowest octave into higher octaves
  4721. nextpitch = prepitch[n] + octstep;
  4722. if(nextpitch > MIDIMAX) {
  4723. done = 1;
  4724. break;
  4725. }
  4726. binpitch[pitchpos++] = nextpitch;
  4727. }
  4728. octstep += SEMITONES_PER_OCTAVE;
  4729. if(done)
  4730. break;
  4731. }
  4732. dz->bincnt = pitchpos; // Remember how many bins we have
  4733. }
  4734. if((dz->parray[PBINTOP] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  4735. sprintf(errstr,"INSUFFICIENT MEMORY to store Pitch-Bin-Top data.\n");
  4736. return(MEMORY_ERROR);
  4737. }
  4738. if((dz->parray[PBINAMP] = (double *)malloc(dz->bincnt * 4 * sizeof(double)))==NULL) {
  4739. sprintf(errstr,"INSUFFICIENT MEMORY to store Pitch-Bin-Amp Data.\n");
  4740. return(MEMORY_ERROR);
  4741. }
  4742. if((dz->iparray[PCNTBIN] = (int *)malloc(dz->bincnt * 4 * sizeof(int)))==NULL) {
  4743. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Counting Data.\n");
  4744. return(MEMORY_ERROR);
  4745. }
  4746. }
  4747. // 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)
  4748. bintop = dz->parray[PBINTOP];
  4749. for(m=1;m< 4;m++) {
  4750. offset = dz->bincnt * m; // 4 arrays, 1 for each formant
  4751. for(n=0,k=offset;n<dz->bincnt;n++,k++)
  4752. binpitch[k] = binpitch[n];
  4753. }
  4754. for(n=1;n < dz->bincnt-1;n++) { // For HS gaps width of pitch-search bins assumed to be a semitone
  4755. bintop[n] = min((binpitch[n+1] - binpitch[n])/2.0,0.5); // (or less, of gap between bins is less than a semitone)
  4756. bintop[n] += binpitch[n];
  4757. }
  4758. 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
  4759. bintop[n] = min(127.0,bintop[n]); // Unless that takes it above 127
  4760. bintop[0] = binpitch[1] - (bintop[1] - binpitch[1]); // Lower bound (pitchtop[0]) of lowest bin (binpitch[1]) same distance from centre as upper bound
  4761. bintop[0] = max(0.0,bintop[0]); // Unless that takes it below zero
  4762. memset((char *)dz->iparray[PCNTBIN],0,dz->bincnt * 4 *sizeof(int)); // Preset arrays where values are ADDED into them
  4763. memset((double *)dz->parray[PBINAMP],0,dz->bincnt * 4 * sizeof(double));
  4764. if((dz->parray[FPITCHES] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  4765. sprintf(errstr,"INSUFFICIENT MEMORY to store pitches actually used by filter.\n");
  4766. return(MEMORY_ERROR);
  4767. }
  4768. return FINISHED;
  4769. }
  4770. /**************************** HANDLE_THE_PQUANTISE_SPECIAL_DATA ****************************/
  4771. int handle_the_pquantise_special_data(char *str,dataptr dz)
  4772. {
  4773. int exit_status, is_hs = -1, is_thf = 0, is_scale = 0, is_elacs = 0, scale_division = 12, entrycnt = 0, pitchsort = 0;
  4774. int cntpitches = 0, linecnt, pitchpos, oct1pitchpos, step, n, m, done, mindiffat, nubincnt;
  4775. double dummy = 0.0, reference_pitch = 60.0, ratio, octstep, nextpitch, mindiff, thisdiff, nupitch, pseudoct_size = 12.0;
  4776. double trueoct_cnt, semitone_len, thispitch, octfoot, lasttime = 0.0;
  4777. FILE *fp;
  4778. double *pset = NULL, *prepitch;
  4779. int arraysize;
  4780. char temp[800], *p;
  4781. dz->timedhf = 0;
  4782. if((dz->mode == F_PCHRAND || dz->mode == F_SINUS) && (!strcmp(str,"0") || !strcmp(str,"0.0"))) {
  4783. dz->quantcnt = 0;
  4784. return FINISHED;
  4785. }
  4786. if((fp = fopen(str,"r"))==NULL) {
  4787. sprintf(errstr,"Cannot open file %s to read data.\n",str);
  4788. return(DATA_ERROR);
  4789. }
  4790. linecnt = 0;
  4791. while(fgets(temp,200,fp)!=NULL) {
  4792. p = temp;
  4793. while(isspace(*p))
  4794. p++;
  4795. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  4796. continue;
  4797. if(*p == '#') { // Look for #HF, #HS, or #SCALES marker
  4798. strip_end_space(p);
  4799. if(strcmp(p,"#HS") == 0) {
  4800. is_hs = 1;
  4801. // is_pitches = 1;
  4802. } else if(strcmp(p,"#HF") == 0) {
  4803. is_hs = 0;
  4804. // is_pitches = 1;
  4805. } else if(strcmp(p,"#SCALE") == 0) {
  4806. is_hs = 0;
  4807. is_scale = 1;
  4808. // is_pitches = 1;
  4809. } else if(strcmp(p,"#ELACS") == 0) {
  4810. is_hs = 0;
  4811. is_elacs = 1;
  4812. // is_pitches = 1;
  4813. } else if(strcmp(p,"#THF") == 0) {
  4814. is_hs = 0;
  4815. is_thf = 1;
  4816. dz->timedhf = 1;
  4817. // is_pitches = 1;
  4818. }
  4819. else {
  4820. sprintf(errstr,"Invalid Field, Set, or Scale marker (%s) on line %d in file %s\n",p,linecnt+1,str);
  4821. return(DATA_ERROR);
  4822. }
  4823. } else {
  4824. while(get_float_from_within_string(&p,&dummy)) {
  4825. if(is_scale) { // For scales, we need to find note-per-oct and ref-pitch
  4826. switch(cntpitches) {
  4827. case(0):
  4828. if(dummy < 1 || dummy > MAXSCALECNT) {
  4829. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4830. return(DATA_ERROR);
  4831. }
  4832. scale_division = (int)round(dummy);
  4833. break;
  4834. case(1):
  4835. if(dummy < 0 || dummy > MIDIMAX) {
  4836. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4837. return(DATA_ERROR);
  4838. }
  4839. reference_pitch = dummy;
  4840. break;
  4841. default:
  4842. sprintf(errstr,"Too many vals specified for scale in file %s: need only notes-per-octave and (MIDI)ref-pitch.\n",str);
  4843. return(DATA_ERROR);
  4844. }
  4845. } else if(is_elacs) { // For elacs, we need to find "octave"-size,note-per-oct and ref-pitch
  4846. switch(cntpitches) {
  4847. case(0):
  4848. if(dummy < PSEUDOCTMIN || dummy > PSEUDOCTMAX) {
  4849. sprintf(errstr,"\"Octave\" size (%d) at line %d out of range (%d to %d)\n",(int)round(dummy),linecnt+1,PSEUDOCTMIN,PSEUDOCTMAX);
  4850. return(DATA_ERROR);
  4851. }
  4852. pseudoct_size = (int)round(dummy);
  4853. break;
  4854. case(1):
  4855. if(dummy < 1 || dummy > MAXSCALECNT) {
  4856. sprintf(errstr,"Scale division (%d) at line %d out of range (1 to %d)\n",(int)round(dummy),linecnt+1,MAXSCALECNT);
  4857. return(DATA_ERROR);
  4858. }
  4859. scale_division = (int)round(dummy);
  4860. if((double)pseudoct_size/(double)scale_division < .01) {
  4861. sprintf(errstr,"Scale steps per true octave (%.lf) too small (Minimum %.2lf)\n",(double)pseudoct_size/(double)scale_division,0.01);
  4862. return(DATA_ERROR);
  4863. }
  4864. break;
  4865. case(2):
  4866. if(dummy < 0 || dummy > MIDIMAX) {
  4867. sprintf(errstr,"Invalid reference pitch data (%lf) for scale, at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4868. return(DATA_ERROR);
  4869. }
  4870. reference_pitch = dummy;
  4871. break;
  4872. default:
  4873. sprintf(errstr,"Too many vals for escal in file %s: need only \"oct\"-size, notes-per-\"oct\" and (MIDI)ref-pitch.\n",str);
  4874. return(DATA_ERROR);
  4875. }
  4876. } else if(is_thf) { // For thf, we need to find several hfs and their times
  4877. if(entrycnt == 0)
  4878. pitchsort = cntpitches;
  4879. else
  4880. pitchsort = cntpitches % entrycnt;
  4881. switch(pitchsort) {
  4882. case(0):
  4883. if(linecnt == 1) {
  4884. if(dummy != 0.0) {
  4885. sprintf(errstr,"First time must be zero for a time-changing HF, in file %s\n",str);
  4886. return(DATA_ERROR);
  4887. }
  4888. } else if(dummy <= lasttime) {
  4889. sprintf(errstr,"Times do not advance (%lf : %lf) from line %d to line %d in file %s\n",lasttime,dummy,linecnt-1,linecnt,str);
  4890. return(DATA_ERROR);
  4891. }
  4892. lasttime = dummy;
  4893. break;
  4894. default:
  4895. if(dummy < 0.0 || dummy > 127) {
  4896. sprintf(errstr,"Pitch value (%lf) out of range (0-127) in %d in file %s\n",dummy,linecnt,str);
  4897. return(DATA_ERROR);
  4898. }
  4899. break;
  4900. }
  4901. } else { // For HS or HF we need a set of MIDI values
  4902. if(dummy < 0 || dummy > MIDIMAX) {
  4903. sprintf(errstr,"Invalid pitch data (%lf) at line %d. (Range MIDI 0 - 127)\n",dummy,linecnt+1);
  4904. return(DATA_ERROR);
  4905. }
  4906. }
  4907. cntpitches++;
  4908. }
  4909. }
  4910. if(linecnt > 0 && is_thf) {
  4911. if(linecnt == 1)
  4912. entrycnt = cntpitches;
  4913. else if(cntpitches % entrycnt != 0) {
  4914. sprintf(errstr,"Lines %d & %d are not of same length in file %s\n",linecnt,linecnt+1,str);
  4915. return(DATA_ERROR);
  4916. }
  4917. }
  4918. linecnt++;
  4919. }
  4920. if(is_hs == -1) {
  4921. sprintf(errstr,"No data for Harmonic-Field, Harmonic-Set or Scale-type specified in file %s.\n",str);
  4922. return(DATA_ERROR);
  4923. }
  4924. if(is_scale || is_elacs) {
  4925. if(is_scale) {
  4926. arraysize = (scale_division * MIDIOCTSPAN) + 1;
  4927. if((dz->parray[QUANTPITCH] = (double *)malloc(arraysize * sizeof(double)))==NULL) {
  4928. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4929. return(MEMORY_ERROR);
  4930. }
  4931. pset = dz->parray[QUANTPITCH];
  4932. pitchpos = 0;
  4933. // SPECIFY PITCHES IN 1ST 8VA
  4934. switch(scale_division) {
  4935. case(1):// fall thro // For rational divisors of 12
  4936. case(2):// fall thro
  4937. case(3):// fall thro
  4938. case(4):// fall thro
  4939. case(6):// fall thro
  4940. case(12):
  4941. step = (int)round(SEMITONES_PER_OCTAVE)/scale_division;
  4942. for(n = 0;n < scale_division;n+=step)
  4943. pset[pitchpos++] = (double)n;
  4944. break;
  4945. default: // Otherwise
  4946. for(n = 0;n < scale_division;n++) {
  4947. ratio = (double)n/(double)scale_division;
  4948. pset[pitchpos++] = SEMITONES_PER_OCTAVE * ratio;
  4949. }
  4950. break;
  4951. }
  4952. // SPECIFY PITCHES IN ALL OTHER 8VAs
  4953. done = 0;
  4954. octstep = 0;
  4955. for(m=1;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  4956. oct1pitchpos = 1; // Point to vals in lowest 8va
  4957. octstep += SEMITONES_PER_OCTAVE;
  4958. for(n=0;n<scale_division;n++) { // Copy these, N octaves higher, into higher octaves
  4959. nextpitch = pset[oct1pitchpos++] + octstep;
  4960. if(nextpitch > MIDIMAX) {
  4961. done = 1;
  4962. break;
  4963. }
  4964. pset[pitchpos++] = nextpitch;
  4965. }
  4966. if(done)
  4967. break;
  4968. }
  4969. dz->bincnt = pitchpos; // Remember how many bins we have
  4970. } else { // is_elacs
  4971. arraysize = 0;
  4972. trueoct_cnt = 0;
  4973. semitone_len = 0;
  4974. while(trueoct_cnt < MIDIOCTSPAN) {
  4975. arraysize += scale_division;
  4976. semitone_len += pseudoct_size;
  4977. trueoct_cnt = (int)floor(semitone_len/SEMITONES_PER_OCTAVE);
  4978. }
  4979. if((dz->parray[QUANTPITCH] = (double *)malloc(arraysize * 4 * sizeof(double)))==NULL) {
  4980. sprintf(errstr,"INSUFFICIENT MEMORY to store Filter-Pitch-Bin data.\n");
  4981. return(MEMORY_ERROR);
  4982. }
  4983. pset = dz->parray[QUANTPITCH];
  4984. pitchpos = 0; // Dummy entry in position [0] - (allows pitchtop counter to tally with pitch centre conter)
  4985. // SPECIFY PITCHES IN EACH pseudo8va for all pseudo8vas until MIDIMAX is reached
  4986. thispitch = 0.0;
  4987. octfoot = 0.0;
  4988. while(thispitch <= MIDIMAX) {
  4989. for(n = 0;n < scale_division;n++) {
  4990. ratio = (double)n/(double)scale_division;
  4991. if((thispitch = (pseudoct_size * ratio) + octfoot) > MIDIMAX) {
  4992. break;
  4993. }
  4994. pset[pitchpos++] = thispitch;
  4995. }
  4996. octfoot += pseudoct_size;
  4997. }
  4998. dz->bincnt = pitchpos; // Remember how many bins we have
  4999. }
  5000. if(is_elacs || !flteq(fmod(reference_pitch,SEMITONES_PER_OCTAVE),0.0)) { // Either, is_elacs, so pitches not guaranteed to include reference_pitch
  5001. // OR, Reference-pitch is not at multiple of 12
  5002. // Find pitch closest to reference pitch, and find interval distance to ref-pitch
  5003. mindiff = HUGE;
  5004. mindiffat = 0;
  5005. for(n = 1; n < dz->bincnt; n++) { // pset[0] is a dummy
  5006. thisdiff = fabs(reference_pitch - pset[n]);
  5007. if(thisdiff < mindiff) {
  5008. mindiff = thisdiff;
  5009. mindiffat = n;
  5010. }
  5011. }
  5012. // Now transpose set so it includes ref-pitch
  5013. mindiff = reference_pitch - pset[mindiffat];
  5014. if(mindiff > 0.0) {
  5015. for(n = 1; n < dz->bincnt; n++) {
  5016. nupitch = pset[n] + mindiff;
  5017. if(nupitch > 127)
  5018. break;
  5019. pset[n] = nupitch;
  5020. }
  5021. dz->bincnt = n; // May be smaller than orig, if pset pushed eyond 127
  5022. } else if(mindiff < 0.0) {
  5023. nubincnt = 1;
  5024. for(n = 1; n < dz->bincnt; n++) {
  5025. nupitch = pset[n] + mindiff;
  5026. if(nupitch >= 0.0) // pset now below zero are ignored, so the new bincnt (m) does not increment
  5027. pset[nubincnt++] = nupitch; // Otherwise new pset are written over orig pset (possibly lower in array - but never higher!!)
  5028. }
  5029. dz->bincnt = nubincnt;
  5030. }
  5031. }
  5032. } else {
  5033. // If not scale: create array to store pitchdata initially read from file
  5034. if((dz->parray[PREPICH] = (double *)malloc((cntpitches + 1) * sizeof(double)))==NULL) {
  5035. sprintf(errstr,"INSUFFICIENT MEMORY to store Initial Filter Pitch Data.\n");
  5036. return(MEMORY_ERROR);
  5037. }
  5038. prepitch = dz->parray[PREPICH];
  5039. rewind(fp);
  5040. linecnt = 0;
  5041. cntpitches = 0;
  5042. while(fgets(temp,200,fp)!=NULL) {
  5043. p = temp;
  5044. while(isspace(*p))
  5045. p++;
  5046. if(*p == ';' || *p == ENDOFSTR) // Allow comments in file
  5047. continue;
  5048. if(*p == '#')
  5049. continue;
  5050. while(get_float_from_within_string(&p,&dummy))
  5051. prepitch[cntpitches++] = dummy;
  5052. linecnt++;
  5053. }
  5054. fclose(fp);
  5055. if(is_thf) { // Sort each line of pitches & transpose into lowest octave
  5056. dz->quantcnt = entrycnt; // quantcnt isthe number of quantising pitches per line
  5057. dz->itemcnt = linecnt; // itemcnt is the number of different quantisation sets
  5058. sort_pitches_for_tvary_hf(dz->quantcnt,dz->itemcnt,dz);
  5059. dz->bincnt = (((entrycnt-1) * MIDIOCTSPAN) * dz->itemcnt) + dz->itemcnt;
  5060. // pitches dupl_vals for extra entry
  5061. // per in all every for time
  5062. // line 8vas line in each line
  5063. } else {
  5064. dz->itemcnt = cntpitches;
  5065. dz->itemcnt = sort_pitches(dz); // Some pitches may be duplicated: they also need to be in ascending order
  5066. if(is_hs) {
  5067. dz->quantcnt = dz->itemcnt; // Number of pitches to quantise to is exactly those entered
  5068. dz->bincnt = dz->itemcnt + 1; // Space for all entered pitches + dummy value at [0]
  5069. } else {
  5070. for(n = 0;n < dz->itemcnt; n++) { // For HF, duplicate pitches over all 8vas
  5071. while(prepitch[n] >= 0.0)
  5072. prepitch[n] -= SEMITONES_PER_OCTAVE; // 1st transpose all pitches into lowest octave
  5073. prepitch[n] += SEMITONES_PER_OCTAVE;
  5074. }
  5075. dz->itemcnt = sort_pitches(dz); // After transposition, some pitches may be duplicated
  5076. dz->bincnt = (dz->itemcnt * MIDIOCTSPAN) + 1; // pitches are to be duplicated in all 8vas + we need the dummy val at [0]
  5077. }
  5078. }
  5079. if((dz->parray[QUANTPITCH] = (double *)malloc(dz->bincnt * sizeof(double)))==NULL) {
  5080. sprintf(errstr,"INSUFFICIENT MEMORY to store Quantisation pitch field.\n");
  5081. return(MEMORY_ERROR);
  5082. }
  5083. pset = dz->parray[QUANTPITCH];
  5084. if(is_hs) // For HS, merely copy pitches into final array
  5085. memcpy((char *)dz->parray[QUANTPITCH],(char *)dz->parray[PREPICH],dz->bincnt * sizeof(double));
  5086. else if(is_thf) { // For THF, copy pitches in each line-set into all 8vas in MIDI range
  5087. if((exit_status = octaviate_and_store_timed_hf_data(dz))<0)
  5088. return exit_status;
  5089. } else { // For HF, copy pitches into all 8vas in MIDI range
  5090. done = 0;
  5091. pitchpos = 0;
  5092. octstep = 0;
  5093. for(m=0;m < MIDIOCTSPAN; m++) { // For every 8va in total MIDI range
  5094. for(n=0;n<dz->itemcnt;n++) { // Copy pitches in lowest octave into higher octaves
  5095. nextpitch = prepitch[n] + octstep;
  5096. if(nextpitch > MIDIMAX) {
  5097. done = 1;
  5098. break;
  5099. }
  5100. pset[pitchpos++] = nextpitch;
  5101. }
  5102. octstep += SEMITONES_PER_OCTAVE;
  5103. if(done)
  5104. break;
  5105. }
  5106. dz->quantcnt = pitchpos; // Remember how many bins we have
  5107. }
  5108. }
  5109. return FINISHED;
  5110. }
  5111. /****************************************** SORT_PITCHES ***************************/
  5112. int sort_pitches(dataptr dz)
  5113. {
  5114. int n, m;
  5115. double temp, *prepitch = dz->parray[PREPICH];
  5116. int len = dz->itemcnt;
  5117. for(n = 0; n < len - 1; n++) { // Sort into ascending order
  5118. for(m = n+1; m < len;m++) {
  5119. if(prepitch[m] < prepitch[n]) {
  5120. temp = prepitch[m];
  5121. prepitch[m] = prepitch[n];
  5122. prepitch[n] = temp;
  5123. }
  5124. }
  5125. }
  5126. for(n = 0; n < len-1; n++) { // Eliminate duplicates
  5127. if(flteq(prepitch[n+1],prepitch[n])) {
  5128. for(m = n+1;m < len;m++)
  5129. prepitch[m-1] = prepitch[m];
  5130. len--;
  5131. }
  5132. }
  5133. return len;
  5134. }
  5135. /****************************************** SORT_PITCHES_FOR_TVARY_HF ***************************/
  5136. int sort_pitches_for_tvary_hf(int entrycnt,int linecnt,dataptr dz)
  5137. {
  5138. int line, line_cnt, later_line_cnt, abs_cnt, later_abs_cnt;
  5139. double temp, *prepitch = dz->parray[PREPICH];
  5140. for(line = 0; line < linecnt; line++) { // For each line
  5141. for(line_cnt = 1, abs_cnt = line * entrycnt + 1; line_cnt < entrycnt - 1; line_cnt++,abs_cnt++) { // Ignoring the first (time) entry
  5142. for(later_line_cnt = line_cnt+1,later_abs_cnt = abs_cnt+1; later_line_cnt < entrycnt;later_line_cnt++,later_abs_cnt++) {
  5143. if(prepitch[later_abs_cnt] < prepitch[abs_cnt]) { // Sort pitches into ascending order
  5144. temp = prepitch[later_abs_cnt];
  5145. prepitch[later_abs_cnt] = prepitch[abs_cnt];
  5146. prepitch[abs_cnt] = temp;
  5147. }
  5148. }
  5149. }
  5150. for(line_cnt = 1, abs_cnt = line * entrycnt + 1; line_cnt < entrycnt; line_cnt++,abs_cnt++) { // transpose all pitches into lowest 8va
  5151. while(prepitch[abs_cnt] >= 0.0)
  5152. prepitch[abs_cnt] -= SEMITONES_PER_OCTAVE;
  5153. prepitch[abs_cnt] += SEMITONES_PER_OCTAVE;
  5154. }
  5155. }
  5156. return FINISHED;
  5157. }
  5158. /****************************************** FORMANTS_MAKEFILT ***************************/
  5159. int formants_makefilt(int inner_lpcnt,int *times_index,dataptr dz)
  5160. {
  5161. int exit_status, n, cc, vc, k, j, spstt, spend, ccstt, ccend, vcstt, peakloc, newcc, peakno, get_fundamental = 0;
  5162. float frqstt, frqend, thisamp, newfrq = 0.0;
  5163. double thispch, maxamp;
  5164. double *bintop = dz->parray[PBINTOP], *binamp = dz->parray[PBINAMP];
  5165. int *bincnt = dz->iparray[PCNTBIN], *peakat = dz->iparray[PEAKPOS];
  5166. int *ftimes = dz->lparray[FTIMES];
  5167. peakat += inner_lpcnt * PKBLOK;
  5168. if(*times_index < dz->timeblokcnt) { // If their is a list of times, and we haven't reached end of it
  5169. if(inner_lpcnt >= ftimes[*times_index]) { // If we've got to time-boundary for next filter
  5170. if((exit_status = build_filter(*times_index,dz)) < 0)
  5171. return(exit_status); // build the filter so far.
  5172. for(n = 0; n < dz->bincnt; n++) { // Then zero the counting and amplitude sum bins for the next block of windows
  5173. bincnt[n] = 0;
  5174. binamp[n] = 0.0;
  5175. }
  5176. (*times_index)++;
  5177. }
  5178. }
  5179. for(n = 0; n < PKBLOK-1; n+=2) { // Going through the trofs in pairs
  5180. peakno = n/2;
  5181. if(dz->fundamental && n == 0)
  5182. get_fundamental = 1;
  5183. spstt = peakat[n]; // Get specenvamp locations of 2 adjacent trofs.
  5184. spend = peakat[n+2];
  5185. frqstt = dz->specenvtop[spstt]; // Find freq of top frq-edge of lower trof
  5186. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  5187. frqend = dz->specenvtop[spend-1]; // Find freq of bottom frq-edge of upper trof
  5188. ccend = (int)ceil(frqend/dz->chwidth);
  5189. maxamp = -HUGE; // Find the flbuptr location of maximum amplitude.
  5190. vcstt = ccstt * 2;
  5191. peakloc = ccstt;
  5192. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  5193. if(dz->flbufptr[0][AMPP] > maxamp) {
  5194. maxamp = dz->flbufptr[0][AMPP];
  5195. peakloc = cc;
  5196. }
  5197. }
  5198. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  5199. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  5200. return exit_status;
  5201. if(newfrq > 0.0) // i.e. if we really have pitch data here
  5202. peakloc = newcc;
  5203. get_fundamental = 0; // Only (try to) get fundamental when in first formant
  5204. }
  5205. vc = peakloc;
  5206. thisamp = dz->flbufptr[0][AMPP];
  5207. thispch = unchecked_hztomidi((double)dz->flbufptr[0][FREQ]);
  5208. if(thispch > 0 && thispch <= 127) {
  5209. for(k = 1,j= (peakno*dz->bincnt)+1;k < dz->bincnt;k++,j++) { // Find which bin (if any) the pitch falls in
  5210. if(thispch < bintop[k] && thispch > bintop[k-1]) {
  5211. bincnt[j]++; // Count occurences of this pitch
  5212. binamp[j] += thisamp; // Sum amps of all occurences of this pitch
  5213. break;
  5214. }
  5215. }
  5216. }
  5217. }
  5218. return FINISHED;
  5219. }
  5220. /****************************************** BUILD_FILTER ***************************/
  5221. int build_filter(int times_index,dataptr dz)
  5222. {
  5223. int n, j, k, z, pch, amp, filtercnt, this_time, next_time, target, get_below = 0, pitchcnt, newpitch, filtlinelen;
  5224. int maxcnt;
  5225. double maxfiltamp = 0.0, maxamp = 0.0, starttime, lasttime = 0.0, tempval, minpitch;
  5226. double *binpitch = dz->parray[PBINPCH], *binamp = dz->parray[PBINAMP];
  5227. double *filtpch = dz->parray[LOCALPCH], *filtamp = dz->parray[LOCALAMP];
  5228. double *pchstore = dz->parray[FILTPICH], *ampstore = dz->parray[FILTAMP];
  5229. double *fpitches = dz->parray[FPITCHES];
  5230. float *filtline, *lastfiltline;
  5231. double lastpch;
  5232. int *countbin = dz->iparray[PCNTBIN];
  5233. int maxat = 0, maxats[MAXFILTVALS];
  5234. int *ftimes = dz->lparray[FTIMES];
  5235. int blokcnt = dz->iparam[FPKCNT] * 4;
  5236. int storepos = (times_index - 1) * blokcnt, storecnt;
  5237. int filtbas, fmntno, fcnt, do_intermediate_line;
  5238. memset((char *)filtpch,0,dz->iparam[FPKCNT] * 4 * sizeof(int));
  5239. memset((char *)filtamp,0,dz->iparam[FPKCNT] * 4 * sizeof(double));
  5240. if(dz->param[FBELOW])
  5241. get_below = 1;
  5242. // FIND MOST PROMINENT PITCHES IN THIS BLOK
  5243. for(fmntno = 0;fmntno < 4;fmntno++) {
  5244. minpitch = 2000;
  5245. filtbas = (fmntno * dz->iparam[FPKCNT]);
  5246. memset((char *)maxats,0,MAXFILTVALS * sizeof(int));
  5247. for(fcnt = 0,filtercnt = filtbas; fcnt < dz->iparam[FPKCNT]; fcnt++,filtercnt++) {
  5248. maxcnt = -1;
  5249. maxat = 0;
  5250. for(j = 1,k = (fmntno*dz->bincnt)+1;j< dz->bincnt;j++,k++) {
  5251. if(countbin[k] > maxcnt) {
  5252. maxcnt = countbin[k]; // Find pitch that occurs most frequently
  5253. maxamp = binamp[k];
  5254. maxat = k;
  5255. } else if(countbin[k] == maxcnt) {
  5256. if(binamp[k] > maxamp) { // If more than 1 pitch is equally frequent
  5257. maxamp = binamp[k]; // Take the one with the greatest amplitude (summed over all occurences)
  5258. maxat = k;
  5259. }
  5260. }
  5261. }
  5262. maxats[fcnt] = maxat;
  5263. filtpch[filtercnt] = binpitch[maxat]; // Set pitch found as a filter pitch
  5264. filtamp[filtercnt] = binamp[maxat];
  5265. countbin[maxat] = 0; // Eliminate this pitch from next search
  5266. minpitch = min(filtpch[filtercnt],minpitch);
  5267. // Freqs Below a given pitch are required, search for
  5268. if(get_below && (minpitch > dz->param[FBELOW])) {
  5269. while(minpitch > dz->param[FBELOW]) {
  5270. target = min(fcnt,dz->iparam[FPKCNT] - 1);
  5271. target += filtbas;
  5272. maxcnt = -1;
  5273. maxat = 0;
  5274. for(j = 1, k = (fmntno * dz->bincnt)+1;j < dz->bincnt;j++,k++) {
  5275. if(countbin[k] > maxcnt) {
  5276. maxcnt = countbin[k]; // Find pitch that occurs most frequently
  5277. maxamp = binamp[k];
  5278. maxat = k;
  5279. } else if(countbin[k] == maxcnt) {
  5280. if(binamp[k] > maxamp) { // If more than 1 pitch is equally frequent
  5281. maxamp = binamp[k]; // Take the one with the greatest amplitude (summed over all occurences)
  5282. maxat = k;
  5283. }
  5284. }
  5285. }
  5286. if(maxcnt <= 0) // IF there are NO suitable low frqs, exit
  5287. break;
  5288. if(binpitch[maxat] < minpitch) {
  5289. filtpch[target] = binpitch[maxat]; // Set pitch found as last filter pitch
  5290. filtamp[target] = binamp[maxat];
  5291. minpitch = binpitch[maxat]; // will; break from loop
  5292. }
  5293. countbin[maxat] = 0; // Eliminate this pitch from next search
  5294. }
  5295. }
  5296. if(maxcnt > 0) // Found minimum, drop searching in other formants
  5297. get_below = 0;
  5298. }
  5299. }
  5300. // SORT INTO ASCENDING PITCH ORDER AND SILENCE DUPLICATES
  5301. for(n = 0; n < blokcnt - 1; n++) {
  5302. for(k = n+1; k < blokcnt; k++) {
  5303. if(filtpch[n] > filtpch[k]) {
  5304. tempval = filtpch[n];
  5305. filtpch[n] = filtpch[k];
  5306. filtpch[k] = tempval;
  5307. tempval = filtamp[n];
  5308. filtamp[n] = filtamp[k];
  5309. filtamp[k] = tempval;
  5310. } else if(flteq(filtpch[n],filtpch[k])) {
  5311. filtamp[k] = 0.0;
  5312. }
  5313. }
  5314. }
  5315. // IF AMPS TO BE RETAINED, FIND MAX, IN ORDER TO NORMALISE
  5316. for(filtercnt = 0; filtercnt < blokcnt; filtercnt++) {
  5317. if(dz->vflag[KEEPAMP])
  5318. maxfiltamp = max(maxfiltamp,filtamp[filtercnt]);
  5319. else if(dz->vflag[KEEPINV]) { // If amps to be inverted, invert them
  5320. if(!flteq(filtamp[filtercnt],0.0))
  5321. filtamp[filtercnt] = 1.0/filtamp[filtercnt];
  5322. maxfiltamp = max(maxfiltamp,filtamp[filtercnt]);
  5323. } else // Otherwise, set all amps to 1
  5324. filtamp[filtercnt] = 1.0;
  5325. }
  5326. if(dz->vflag[KEEPAMP] || dz->vflag[KEEPINV]) { // If amps or invamps retained, normalise
  5327. for(filtercnt = 0; filtercnt < blokcnt; filtercnt++)
  5328. filtamp[filtercnt] /= maxfiltamp;
  5329. }
  5330. // STORE THE FILTER DATA
  5331. for(filtercnt = 0, storecnt = storepos; filtercnt < blokcnt; filtercnt++,storecnt++) {
  5332. pchstore[storecnt] = filtpch[filtercnt];
  5333. ampstore[storecnt] = filtamp[filtercnt];
  5334. }
  5335. // ONCE ALL FILTER DATA GENERATED:
  5336. if(times_index >= dz->timeblokcnt) {
  5337. // FIND 1st DISTINCT PITCH USED
  5338. pitchcnt = 0;
  5339. for(n = 0; n < storecnt; n++) {
  5340. if(ampstore[n] > 0.0) {
  5341. fpitches[0] = pchstore[n];
  5342. pitchcnt++;
  5343. break;
  5344. }
  5345. }
  5346. if(pitchcnt == 0) {
  5347. sprintf(errstr,"NO VALID PITCHES FOUND IN FILTER DATA.\n");
  5348. return DATA_ERROR;
  5349. }
  5350. // FIND ALL DISTINCT PITCHES USED
  5351. while(n < storecnt) {
  5352. if(ampstore[n] > 0.0) {
  5353. newpitch = 1;
  5354. for(k = 0; k < pitchcnt;k++) {
  5355. if(flteq(pchstore[n],pchstore[k])) {
  5356. newpitch = 0;
  5357. break;
  5358. }
  5359. }
  5360. if(newpitch)
  5361. fpitches[pitchcnt++] = pchstore[n];
  5362. }
  5363. n++;
  5364. }
  5365. // SORT DISTINCT PITCHES INTO ASCENDING ORDER && ELIMINATE DUPLICATES
  5366. for(n = 0; n < pitchcnt - 1; n++) {
  5367. for(k = n+1; k < pitchcnt; k++) {
  5368. if(fpitches[n] > fpitches[k]) {
  5369. tempval = fpitches[n];
  5370. fpitches[n] = fpitches[k];
  5371. fpitches[k] = tempval;
  5372. } else if(flteq(fpitches[n],fpitches[k])) {
  5373. if(k < pitchcnt - 1) {
  5374. for(j = k+1;j < pitchcnt;j++)
  5375. fpitches[j-1] = fpitches[j];
  5376. }
  5377. pitchcnt--;
  5378. k--;
  5379. }
  5380. }
  5381. }
  5382. /* TEST *
  5383. for(z = 0;z < pitchcnt;z++)
  5384. fprintf(stderr,"%.1lf ",fpitches[z]);
  5385. fprintf(stderr,"\n");
  5386. * TEST */
  5387. // ELIMINATE ANY PITCH ZEROS FROM PITCHES TO BE USED IN FILTER
  5388. for(n = 0; n < pitchcnt; n++) {
  5389. if(fpitches[n] <= 0.0) {
  5390. if(n < pitchcnt - 1) {
  5391. for(k = n+1;k < pitchcnt;k++)
  5392. fpitches[k-1] = fpitches[k];
  5393. }
  5394. pitchcnt--;
  5395. }
  5396. }
  5397. filtlinelen = (pitchcnt * 2)+1;
  5398. if((dz->fptr[FILTLINE] = (float *)malloc(filtlinelen * sizeof(float)))==NULL) {
  5399. sprintf(errstr,"INSUFFICIENT MEMORY to store varibank filter line-entry data.\n");
  5400. return(MEMORY_ERROR);
  5401. }
  5402. if((dz->fptr[LASTFLINE] = (float *)malloc(filtlinelen * sizeof(float)))==NULL) {
  5403. sprintf(errstr,"INSUFFICIENT MEMORY to store varibank filter line-entry data.\n");
  5404. return(MEMORY_ERROR);
  5405. }
  5406. filtline = dz->fptr[FILTLINE];
  5407. lastfiltline = dz->fptr[LASTFLINE];
  5408. // OUTPUT THE FILTER
  5409. for(this_time = 0,next_time = 1; this_time < dz->timeblokcnt; this_time++,next_time++) {
  5410. starttime = ftimes[this_time] * dz->frametime;
  5411. // endtime = ftimes[next_time] * dz->frametime; // There are (say) 5 times and 4 stores
  5412. storepos = this_time * blokcnt;
  5413. filtline[0] = (float)starttime;
  5414. for(z = 0,pch = 1,amp = 2;z < pitchcnt;z++,pch+=2,amp+=2) {
  5415. filtline[pch] = (float)fpitches[z];
  5416. filtline[amp] = 0.0; // Establish a zero-amp line for filter
  5417. }
  5418. for(n = 0,k = storepos; n < filtercnt; n++,k++) {
  5419. if(pchstore[k] <= 0.0) { // Interpolate through any pitch-zeros
  5420. j = storepos;
  5421. lastpch = pchstore[k];
  5422. while(lastpch <= 0.0) {
  5423. j -= blokcnt;
  5424. if(j < 0)
  5425. break;
  5426. lastpch = pchstore[j];
  5427. }
  5428. while(lastpch <= 0.0) {
  5429. j += blokcnt;
  5430. if(j > dz->iparam[FPKCNT] * 4 * dz->timeblokcnt)
  5431. break;
  5432. lastpch = pchstore[j];
  5433. }
  5434. if(lastpch <= 0.0)
  5435. pchstore[k] = -1.0; // If truly a zero (i.e. at no time is this pitch NOT a zero) mark as such
  5436. else
  5437. pchstore[k] = lastpch;
  5438. }
  5439. for(pch = 1,amp=2;pch < filtlinelen;pch+=2,amp+=2) { // For each pitch used at this time
  5440. if(pchstore[k] == filtline[pch]) { // Activate this pitch (turn on amp) in the filter
  5441. filtline[amp] = (float)ampstore[k];
  5442. break;
  5443. }
  5444. }
  5445. }
  5446. if(this_time > 0) {
  5447. do_intermediate_line = 0;
  5448. for(pch = 1,amp = 2;pch < filtlinelen;pch+=2,amp+=2) {
  5449. if(filtline[amp] != lastfiltline[amp]) { // If the amplitude of any pitch in filter changes
  5450. do_intermediate_line = 1;
  5451. break;
  5452. }
  5453. }
  5454. if(do_intermediate_line) { // Output an intermediate line, half-way between this time and last-time
  5455. fprintf(dz->fp,"%lf ",(lasttime + starttime)/2.0);
  5456. for(z=1; z < filtlinelen;z++) // With the values from the previous time,
  5457. fprintf(dz->fp,"%lf ",lastfiltline[z]); // So that an amplitude fade or rise will happen in 1/2 duration of previous block
  5458. fprintf(dz->fp,"\n");
  5459. }
  5460. }
  5461. for(z=0; z < filtlinelen;z++) // Output the filter line at this time
  5462. fprintf(dz->fp,"%lf ",filtline[z]);
  5463. fprintf(dz->fp,"\n");
  5464. // Remember this line, in case we need to construct intermediate line
  5465. memcpy((char *)lastfiltline,(char *)filtline,filtlinelen * sizeof(float));
  5466. lasttime = starttime;
  5467. }
  5468. }
  5469. return FINISHED;
  5470. }
  5471. /**************************** FIND_FUNDAMENTAL *************************/
  5472. int find_fundamental(float thisfrq,double target,int peakcc,float *newfrq,dataptr dz)
  5473. {
  5474. int cc, vc, fund_at = -1, divisor = 2;
  5475. double goalfrq, maxamp = -HUGE;
  5476. float foundfrq = thisfrq;
  5477. if(target == 0.0)
  5478. target = thisfrq/* /2 */;
  5479. while(fund_at < 0) {
  5480. goalfrq = thisfrq/(double)divisor;
  5481. if(goalfrq < target * TWO_OVER_THREE)
  5482. break;
  5483. for(cc=0,vc=0;cc < peakcc;cc++,vc+=2) {
  5484. if(equivalent_pitches(dz->flbufptr[0][FREQ],goalfrq,dz) && dz->flbufptr[0][AMPP] > maxamp) {
  5485. maxamp = dz->flbufptr[0][AMPP];
  5486. foundfrq = dz->flbufptr[0][FREQ];
  5487. fund_at = cc;
  5488. }
  5489. }
  5490. if(fund_at < 0)
  5491. divisor++;
  5492. }
  5493. *newfrq = foundfrq; // If no new frq found, newfrq defaults to input frq
  5494. if(fund_at >= 0)
  5495. return fund_at;
  5496. return peakcc; // If no new frq found, new chan defaults to original chan
  5497. }
  5498. /**************************** EQUIVALENT_PITCHES *************************/
  5499. int equivalent_pitches(double frq1, double frq2, dataptr dz)
  5500. {
  5501. double ratio;
  5502. int iratio;
  5503. double intvl;
  5504. ratio = frq1/frq2;
  5505. iratio = round(ratio);
  5506. if(iratio!=1)
  5507. return(FALSE);
  5508. if(ratio > iratio)
  5509. intvl = ratio/(double)iratio;
  5510. else
  5511. intvl = (double)iratio/ratio;
  5512. if(intvl > dz->in_tune)
  5513. return FALSE;
  5514. return TRUE;
  5515. }
  5516. /**************************** FORMANTS_MOVE *************************/
  5517. int formants_move(int inner_lpcnt,dataptr dz)
  5518. {
  5519. int exit_status, truecnt, fno, paramno = 0, lotrofchan = 0, peakchan = 0, hitrofchan = 0, cc, vc, top_hno;
  5520. float lotrofamp = 0.0, peakamp = 0.0, hitrofamp = 0.0, the_fundamental = 0.0, frq;
  5521. double frqoffset, pre_amptotal = 0.0, post_amptotal = 0.0;
  5522. float *peaktrof = dz->fptr[PKTROF];
  5523. int *pos = dz->iparray[PEAKPOS];
  5524. pos += inner_lpcnt * PKBLOK;
  5525. peaktrof += inner_lpcnt * PKBLOK;
  5526. if(dz->fundamental)
  5527. the_fundamental = dz->pitches[inner_lpcnt];
  5528. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  5529. return(exit_status);
  5530. if(dz->xclude_nonh || dz->vflag[SQZ_KHM]) {
  5531. top_hno = 0;
  5532. for(cc = 0, vc = 0; cc < dz->clength; cc++, vc+=2) {
  5533. frq = dz->flbufptr[0][FREQ];
  5534. if(dz->xclude_nonh) { // If excluding non-harmonic data
  5535. if(the_fundamental > 0.0 && !channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  5536. dz->flbufptr[0][AMPP] = 0.0f; // If the window has no pitch, or the frq is not a harmonic of fundamental
  5537. continue; // zero it
  5538. }
  5539. } else if(dz->vflag[SQZ_KHM]) { // If suppressing harmonics
  5540. if(the_fundamental > 0.0) { // IF the chanfrq is a harmonic, zero it
  5541. if(channel_holds_harmonic(the_fundamental,frq,cc,&top_hno,dz)) {
  5542. dz->flbufptr[0][AMPP] = 0.0f;
  5543. continue;
  5544. }
  5545. }
  5546. } // If there is no pitch (or pitch value has NOT been interpolated thro unpitched area)
  5547. if(the_fundamental < 0.0) { // this means that we have flagged up non-pitch and silence for deletion
  5548. dz->flbufptr[0][AMPP] = 0.0f; // Zero the channel
  5549. continue;
  5550. }
  5551. }
  5552. }
  5553. for(fno = 1;fno <= 4; fno++) {
  5554. truecnt = 0;
  5555. switch(fno) {
  5556. case(1):
  5557. paramno = FMOVE1;
  5558. lotrofchan = pos[0];
  5559. peakchan = pos[1];
  5560. hitrofchan = pos[2];
  5561. lotrofamp = peaktrof[0];
  5562. peakamp = peaktrof[1];
  5563. hitrofamp = peaktrof[2];
  5564. break;
  5565. case(2):
  5566. paramno = FMOVE2;
  5567. lotrofchan = pos[2];
  5568. peakchan = pos[3];
  5569. hitrofchan = pos[4];
  5570. lotrofamp = peaktrof[2];
  5571. peakamp = peaktrof[3];
  5572. hitrofamp = peaktrof[4];
  5573. break;
  5574. case(3):
  5575. paramno = FMOVE3;
  5576. lotrofchan = pos[4];
  5577. peakchan = pos[5];
  5578. hitrofchan = pos[6];
  5579. lotrofamp = peaktrof[4];
  5580. peakamp = peaktrof[5];
  5581. hitrofamp = peaktrof[6];
  5582. break;
  5583. case(4):
  5584. paramno = FMOVE4;
  5585. lotrofchan = pos[6];
  5586. peakchan = pos[7];
  5587. hitrofchan = pos[8];
  5588. lotrofamp = peaktrof[6];
  5589. peakamp = peaktrof[7];
  5590. hitrofamp = peaktrof[8];
  5591. break;
  5592. }
  5593. frqoffset = dz->param[paramno]; // Read appropriate parameter for frq offset of the formant
  5594. if(frqoffset != 0.0) {
  5595. if((exit_status = move_formant(fno,frqoffset,lotrofchan,peakchan,hitrofchan,lotrofamp,peakamp,hitrofamp,&truecnt,dz))<0)
  5596. return exit_status;
  5597. dz->iparray[FCNT][fno] = truecnt;
  5598. }
  5599. }
  5600. if((exit_status = concatenate_moved_formants(dz))<0)
  5601. return exit_status;
  5602. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  5603. return(exit_status);
  5604. if(post_amptotal > pre_amptotal) {
  5605. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  5606. return(exit_status);
  5607. }
  5608. if(dz->param[FMVGAIN] > 0.0 && !flteq(dz->param[FMVGAIN],1.0)) {
  5609. for(vc=0;vc<dz->wanted;vc+=2)
  5610. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FMVGAIN]);
  5611. }
  5612. return FINISHED;
  5613. }
  5614. /**************************** MOVE_FORMANT *************************/
  5615. int move_formant(int fno,double frqoffset,int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp,float hitrofamp,int *truecnt,dataptr dz)
  5616. {
  5617. int exit_status, n, speccnt, chanwidth, is_narrowedabove = 0, is_narrowedbelow = 0;
  5618. float *thisamp = NULL, *thisfrq = NULL, *thispch = NULL;
  5619. double frqcentre, half_specbandwidth, frqstep = 0.0,frqstart = 0.0;
  5620. switch(fno) {
  5621. case(1): thisamp = dz->fptr[FAMP1]; thisfrq = dz->fptr[FFRQ1], thispch = dz->fptr[FPCH1]; break;
  5622. case(2): thisamp = dz->fptr[FAMP2]; thisfrq = dz->fptr[FFRQ2], thispch = dz->fptr[FPCH2]; break;
  5623. case(3): thisamp = dz->fptr[FAMP3]; thisfrq = dz->fptr[FFRQ3], thispch = dz->fptr[FPCH3]; break;
  5624. case(4): thisamp = dz->fptr[FAMP4]; thisfrq = dz->fptr[FFRQ4], thispch = dz->fptr[FPCH4]; break;
  5625. }
  5626. for(n=0;n<dz->specenvcnt;n++) // Flag all new formant data as "unknown"
  5627. thisamp[n] = -1.0;
  5628. speccnt = 0;
  5629. *truecnt = 0; // When formant set to specific frq, Must create bandwidth related to bwidth of (moved) formant
  5630. if(dz->mode == F_MOVE2) { // Use measure of half specenvelope bandwidth
  5631. frqcentre = frqoffset; // CHWIDTH 1 2 3 4 5
  5632. half_specbandwidth = dz->frq_step/2.0; // = bwidth | | | | | | | | | | | | | | |
  5633. chanwidth = (hitrofchan - lotrofchan) + 1; // bwidth --- ------ --------- ------------ ---------------
  5634. if(!dz->vflag[MOV2_NRW]) { // -0.5bw -1bw -1.5bw -2bw -2.5bw
  5635. frqstart = max(0.0,frqcentre - (half_specbandwidth * chanwidth));// Band edge below centre frq This = 1/2chwidth * bwidth = chwidth * 1/2bwidth
  5636. frqstep = dz->frq_step;
  5637. } else {
  5638. frqstart = max(0.0,frqcentre - half_specbandwidth); // Narrow bands use a single bandwidth and slice it
  5639. frqstep = dz->frq_step/(double)chanwidth;
  5640. }
  5641. }
  5642. for(n=lotrofchan;n <= hitrofchan;n++) {
  5643. switch(dz->mode) {
  5644. case(F_MOVE):
  5645. thisfrq[speccnt] = (float)(dz->specenvfrq[n] + frqoffset); // Move the frq positions of the specenv information
  5646. break;
  5647. case(F_MOVE2):
  5648. thisfrq[speccnt] = (float)frqstart; // Reset the frq position of the specenv information
  5649. frqstart += frqstep;
  5650. frqstart = min(frqstart,F_HIFRQ_LIMIT);
  5651. break;
  5652. }
  5653. thisamp[speccnt] = dz->specenvamp[n];
  5654. 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
  5655. is_narrowedbelow = 1; // (And don't attemp to calc pitch if frq falls below 0.0)
  5656. else {
  5657. thispch[speccnt] = (float)log10(thisfrq[speccnt]); // Calc pitch at thus frq
  5658. if(thisfrq[speccnt] > F_HIFRQ_LIMIT) // If anything drops off top of range, note this, keep it and COUNT it
  5659. is_narrowedabove = 1;
  5660. else
  5661. (*truecnt)++; // Count the number of chans which are within range
  5662. }
  5663. speccnt++; // Count the number of channels processed
  5664. }
  5665. if(*truecnt == 0) // i.e. everything is now out of range, so formant contributes nothing to output
  5666. return FINISHED;
  5667. if(is_narrowedbelow) {
  5668. if((exit_status = edgefade_formant(thisfrq,thisamp,thispch, 0, truecnt,lotrofchan,peakchan,hitrofchan,lotrofamp,peakamp,hitrofamp,(float)F_LOFRQ_LIMIT,dz))>0)
  5669. return exit_status; // below,chansused original-trof-peak-trof & their orig amps frqlimit
  5670. } else if(is_narrowedabove) {
  5671. if((exit_status = edgefade_formant(thisfrq,thisamp,thispch, 1, truecnt,lotrofchan,peakchan,hitrofchan,lotrofamp,peakamp,hitrofamp,(float)F_HIFRQ_LIMIT,dz))>0)
  5672. return exit_status; // above,chansused original-trof-peak-trof & their orig amps frqlimit
  5673. }
  5674. return FINISHED;
  5675. }
  5676. /*********************************************** CONCATENATE_MOVED_FORMANTS *****************************************/
  5677. int concatenate_moved_formants(dataptr dz)
  5678. {
  5679. int exit_status, cc, vc, fmnt, startbad = 0, midbad = 0, badstt = 0, k, kk, j ,jj;
  5680. float frq;
  5681. double maxamp, amp, thisspecamp1, valgap, ratio, diff, startval;
  5682. double *spec3_amp = dz->parray[FSPEC3];
  5683. double *multbuf = dz->parray[FMULT];
  5684. float *spec3amps[5], *spec3pchs[5];
  5685. int truecnt[5];
  5686. spec3amps[1] = dz->fptr[FAMP1];
  5687. spec3amps[2] = dz->fptr[FAMP2];
  5688. spec3amps[3] = dz->fptr[FAMP3];
  5689. spec3amps[4] = dz->fptr[FAMP4];
  5690. spec3pchs[1] = dz->fptr[FPCH1];
  5691. spec3pchs[2] = dz->fptr[FPCH2];
  5692. spec3pchs[3] = dz->fptr[FPCH3];
  5693. spec3pchs[4] = dz->fptr[FPCH4];
  5694. truecnt[1] = dz->iparray[FCNT][1];
  5695. truecnt[2] = dz->iparray[FCNT][2];
  5696. truecnt[3] = dz->iparray[FCNT][3];
  5697. truecnt[4] = dz->iparray[FCNT][4];
  5698. if(!(truecnt[1] || truecnt[2] || truecnt[3] || truecnt[4]))
  5699. return FINISHED;
  5700. else
  5701. dz->ischange = 1;
  5702. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc += 2) {
  5703. frq = dz->flbufptr[0][FREQ]; // For the frq at this flbufptr channel
  5704. maxamp = -HUGE;
  5705. for(fmnt = 1; fmnt <= 4; fmnt++) { // Find the largest formant env value in the 4 formant arrays
  5706. getspecenv3amp(frq,&amp,spec3pchs[fmnt],spec3amps[fmnt],truecnt[fmnt],dz);
  5707. maxamp = max(amp,maxamp);
  5708. }
  5709. spec3_amp[cc] = (float)maxamp;
  5710. if(maxamp < 0.0) { // No formant data found
  5711. if(frq > F_HIFRQ_LIMIT)
  5712. multbuf[cc] = 1.0; // For frq range of source above upper frq limit, no change to source
  5713. else
  5714. multbuf[cc] = -1.0; // Otherwise flag that we have no new formant data at this frq (should already be -1 by default)
  5715. } else {
  5716. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5717. return(exit_status); // Find original formant envelope value
  5718. if(thisspecamp1 <= 0.0)
  5719. multbuf[cc] = 0.0;
  5720. else
  5721. multbuf[cc] = maxamp/thisspecamp1; // Change in relation to new specenv value
  5722. }
  5723. }
  5724. startbad = 0; // Now smooth the new formant data curve
  5725. midbad = 0;
  5726. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  5727. if(multbuf[cc] < 0.0) {
  5728. switch(cc) {
  5729. case(0):
  5730. startbad++;
  5731. break;
  5732. default:
  5733. if(startbad)
  5734. startbad++;
  5735. else {
  5736. if(midbad == 0) {
  5737. badstt = cc;
  5738. }
  5739. midbad++;
  5740. }
  5741. break;
  5742. }
  5743. } else {
  5744. if(startbad) { // If no formant info at start
  5745. for(k = 0,kk = (k*2)+1;k < startbad;k++,kk+=2) { // force these envelope vals to take same level as 1st trof
  5746. if(multbuf[cc] == 1.0) // No formant data found in window, maxamp = 0.0
  5747. spec3_amp[k] = 0.0;
  5748. else
  5749. spec3_amp[k] = spec3_amp[cc];
  5750. frq = dz->flbufptr[0][kk];
  5751. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5752. return(exit_status);
  5753. if(thisspecamp1 <= 0.0)
  5754. multbuf[k] = 0.0;
  5755. else
  5756. multbuf[k] = spec3_amp[k]/thisspecamp1; // Change in relation to new (interpolated) specenv value
  5757. }
  5758. startbad = 0;
  5759. } else if(midbad) { // IF no formant info within, interpolate between trofs on either side
  5760. if(multbuf[badstt-1] == 1.0) // No formant data found in window, maxamp = 0.0
  5761. startval = 0.0;
  5762. else
  5763. startval = spec3_amp[badstt-1];
  5764. if(multbuf[cc] == 1.0) // No formant data found in window, maxamp = 0.0: gap = 0.0 - startval
  5765. valgap = -startval;
  5766. else
  5767. valgap = spec3_amp[cc] - startval;
  5768. for(k = 0,j = badstt,jj = (badstt*2)+1; k < midbad;k++,j++,jj+=2) {
  5769. ratio = (double)(k+1)/(double)(midbad+1);
  5770. diff = valgap * ratio;
  5771. spec3_amp[j] = (float)(startval + diff);
  5772. frq = dz->flbufptr[0][jj];
  5773. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5774. return(exit_status);
  5775. if(thisspecamp1 <= 0.0)
  5776. multbuf[j] = 0.0;
  5777. else
  5778. multbuf[j] = spec3_amp[j]/thisspecamp1; // Change in relation to new specenv value
  5779. }
  5780. midbad = 0;
  5781. }
  5782. }
  5783. }
  5784. if(midbad) { // If no formant info at end, force endvals to have same val as trof at end of last formant
  5785. startval = spec3_amp[badstt-1];
  5786. for(cc = badstt, vc = cc*2; cc < dz->clength;cc++,vc+=2) {
  5787. frq = dz->flbufptr[0][FREQ];
  5788. if((exit_status = getspecenvamp(&thisspecamp1,(double)frq,0,dz))<0)
  5789. return(exit_status);
  5790. if(thisspecamp1 <= 0.0)
  5791. multbuf[cc] = 0.0;
  5792. else
  5793. multbuf[cc] = startval/thisspecamp1; // Change in relation to new specenv value
  5794. }
  5795. }
  5796. if(dz->vflag[MOV_ZEROTOP]) { // If top of spectrum (above top formant) to be zeroed
  5797. for(cc = dz->clength - 1;cc >= 0;cc--) { // Search down multbuf whilst ever the multiplier value is 1.0
  5798. if(multbuf[cc] == 1.0) // i.e. multbuf does nothing to the spectrum i.e. no formant data has been moved there.
  5799. multbuf[cc] = 0.0; // and zero this not-reformanted area of the spectrum
  5800. else
  5801. break;
  5802. }
  5803. }
  5804. // Now do the formant transformation!!
  5805. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc += 2)
  5806. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * multbuf[cc]);
  5807. return FINISHED;
  5808. }
  5809. /**************************** EDGEFADE_FORMANT *************************/
  5810. int edgefade_formant(float *thisfrq,float *thisamp,float *thispch,int hi,
  5811. int *nuchanlen, int lotrofchan,int peakchan,int hitrofchan,float lotrofamp,float peakamp, float hitrofamp,float frqlimit,dataptr dz)
  5812. {
  5813. int chanlen, preskirtlen, nupreskirtlen, n, origchanlo, origchanhi;
  5814. double shrinkage, trofrise, fracpos, peakampfoot, peakfracpos, peakamprise, nupeakamprise;
  5815. double nupeakamp, envfoot, origchan, diff, amp, amprise, newamprise, newamp, origchfrac;
  5816. float origamplo, origamphi;
  5817. if(*nuchanlen > 1) {
  5818. chanlen = hitrofchan - lotrofchan; // No of channels originally spanned by formant
  5819. shrinkage = (double)(*nuchanlen)/(double)chanlen; // Shrinkage of formant-size
  5820. preskirtlen = peakchan - lotrofchan; // channel-length of rising skirt to original peak
  5821. trofrise = hitrofamp - lotrofamp; // Change in level between the 2 trofs bracketing the peak
  5822. peakfracpos = (double)preskirtlen/(double)chanlen; // Fractional position of peak between trofs
  5823. peakampfoot = lotrofamp + (trofrise * peakfracpos); // "Foot" of peak lies on the line joining the 2 bracketing trofs
  5824. peakamprise = peakamp - peakampfoot; // "Rise" is height of peak above foot
  5825. nupeakamprise = peakamprise * shrinkage; // Peak height lowered porportionally to shrinkage of format width
  5826. nupeakamp = peakampfoot + nupeakamprise;
  5827. nupreskirtlen = (int)round((double)preskirtlen * shrinkage);// Rising skirt of peak shrunk in size
  5828. for(n = 0; n < nupreskirtlen; n++) { // For each channel in the new preskirt
  5829. fracpos = (double)n/(double)(*nuchanlen);
  5830. envfoot = (trofrise * fracpos) + lotrofamp; // Calculate the value of the trof-line (interp value beween the 2 bracketing trofs)
  5831. origchan = (double)lotrofchan + ((double)chanlen * fracpos);// Which channel-position in ORIG specenv corresponds to this fraction into the skirt
  5832. origchanlo = (int)floor(origchan); // Find the bracketing channels in ORIG specenv
  5833. origchanhi = min(origchanlo+1,dz->specenvcnt-1);
  5834. origchfrac = origchan - (double)origchanlo;
  5835. origamplo = dz->specenvamp[origchanlo];
  5836. origamphi = dz->specenvamp[origchanhi];
  5837. diff = origamphi - origamplo;
  5838. amp = origamplo + (origchfrac * diff); // Use these to interpolate for a value from ORIG specenvamp
  5839. amprise = amp - envfoot; // How far is this level above the trof-line
  5840. newamprise = amprise * shrinkage; // Shrink this rise-above-trof
  5841. newamp = envfoot + newamprise; // and calculate the new env amplitude.
  5842. thisamp[n] = (float)newamp; // store it
  5843. }
  5844. thisamp[n] = (float)nupeakamp; // Set peak to new (shrunk) level
  5845. for(n = nupreskirtlen + 1; n < *nuchanlen; n++) { // Do simil calcs for the post-skirt
  5846. fracpos = (double)n/(double)(*nuchanlen);
  5847. envfoot = (trofrise * fracpos) + lotrofamp;
  5848. origchan = (double)lotrofchan + ((double)chanlen * fracpos);
  5849. origchanlo = (int)floor(origchan);
  5850. origchanhi = min(origchanlo+1,dz->specenvcnt-1);
  5851. origchfrac = origchan - (double)origchanlo;
  5852. origamplo = dz->specenvamp[origchanlo];
  5853. origamphi = dz->specenvamp[origchanhi];
  5854. diff = origamphi - origamplo;
  5855. amp = origamplo + (origchfrac * diff);
  5856. amprise = amp - envfoot;
  5857. newamprise = amprise * shrinkage;
  5858. newamp = envfoot + newamprise;
  5859. thisamp[n] = (float)newamp;
  5860. }
  5861. } else // ELSE if only 1 specenv3val, which will be (start or end) trof,
  5862. n = 1; // set another specenv3val to the other (end or start) trof
  5863. if(hi) { // If falling off top of range
  5864. thisamp[n] = hitrofamp; // Keep the upper trof value at end of new, shrunk formant
  5865. thisfrq[n] = frqlimit; // But set its centre, & its upper limit, to the upper frqlimit
  5866. thispch[n] = (float)log10(frqlimit);
  5867. } else { // If falling off bottom of range
  5868. thisamp[0] = lotrofamp; // Keep the lower trof value at start of new, shrunk formant
  5869. thisfrq[0] = frqlimit; // Force specchan centre to be at lofrqlimit
  5870. thispch[0] = (float)log10(frqlimit);
  5871. }
  5872. n++;
  5873. *nuchanlen = n;
  5874. return FINISHED;
  5875. }
  5876. /**************************** GETSPECENV3AMP *************************/
  5877. int getspecenv3amp(double frq,double *amp,float *thispch,float *thisamp,int speccnt,dataptr dz)
  5878. {
  5879. double pp, ratio, ampdiff;
  5880. int z = 0;
  5881. if(speccnt == 0) { /* FORMANT NOT ACTIVE */
  5882. *amp = -1.0; /* flag no amp specified */
  5883. return(FINISHED);
  5884. }
  5885. if(frq<0.0) { /* FREQ NOT AVAILABLE */
  5886. *amp = -1.0; /* flag no amp specified */
  5887. return(FINISHED);
  5888. }
  5889. if(frq<=1.0) /* if frq very low, specify pitch 0.0 */
  5890. pp = 0.0;
  5891. else
  5892. pp = log10(frq);
  5893. if(pp < thispch[0] || pp > thispch[speccnt-1]) {
  5894. *amp = -1.0; /* If pitch out of range of this specenv3 */
  5895. return(FINISHED); /* flag no amp specified */
  5896. }
  5897. while(thispch[z] < pp){ /* Search for channels spanning frequency */
  5898. z++;
  5899. if(z >= speccnt - 1)
  5900. break;
  5901. } /* Interp in specenvamp-envelope to find amp at this frq */
  5902. ratio = (pp - thispch[z-1])/(thispch[z] - thispch[z-1]);
  5903. ampdiff = thisamp[z] - thisamp[z-1];
  5904. *amp = thisamp[z-1] + (ampdiff * ratio);
  5905. *amp = max(0.0,*amp); /* Avoid -ve amps */
  5906. return(FINISHED);
  5907. }
  5908. /**************************** FWINDOW_SIZE *************************/
  5909. int fwindow_size(dataptr dz)
  5910. {
  5911. dz->shortwins = 0;
  5912. switch(dz->mode) {
  5913. case(F_NARROW): if(dz->vflag[NRW_SW]) dz->shortwins = 1; break;
  5914. case(F_SQUEEZE): if(dz->vflag[SQZ_SW]) dz->shortwins = 1; break;
  5915. case(F_NEGATE): break; // Does not extract spectral envelope, but sues array to store OLD contour
  5916. case(F_MAKEFILT): if(dz->vflag[FLT_SW]) dz->shortwins = 1; break;
  5917. case(F_MOVE): // fall thro
  5918. case(F_MOVE2): if(dz->vflag[MOV_SW]) dz->shortwins = 1; break;
  5919. case(F_INVERT): if(dz->vflag[INVERT_SW]) dz->shortwins = 1; break;
  5920. case(F_ROTATE): if(dz->vflag[ROTATE_SW]) dz->shortwins = 1; break;
  5921. case(F_SUPPRESS): if(dz->vflag[SUPPRESS_SW]) dz->shortwins = 1; break;
  5922. case(F_SEE): if(dz->vflag[SEE_SW]) dz->shortwins = 1; break;
  5923. case(F_SEEPKS): if(dz->vflag[SEEPKS_SW]) dz->shortwins = 1; break;
  5924. case(F_SINUS): if(dz->vflag[FSIN_SW]) dz->shortwins = 1; break;
  5925. case(F_ARPEG): // fall_thro
  5926. case(F_OCTSHIFT): // fall_thro
  5927. case(F_TRANS): // fall_thro
  5928. case(F_FRQSHIFT): // fall_thro
  5929. case(F_RESPACE): // fall_thro
  5930. case(F_PINVERT): // fall_thro
  5931. case(F_PEXAGG): // fall_thro
  5932. case(F_PQUANT): // fall thro
  5933. case(F_PCHRAND): // fall thro
  5934. case(F_RAND): if(dz->vflag[RECOLOR_SW]) dz->shortwins = 1; break;
  5935. case(F_SYLABTROF): break;
  5936. default:
  5937. sprintf(errstr,"Unknown mode in small-window check\n");
  5938. return PROGRAM_ERROR;
  5939. }
  5940. return FINISHED;
  5941. }
  5942. //////////////////////////////////
  5943. // GETTING THE PITCH //
  5944. //////////////////////////////////
  5945. /***************************** INITIALISE_PITCHWORK *************************/
  5946. int initialise_pitchwork(int is_launched,dataptr dz)
  5947. {
  5948. int exit_status;
  5949. if((exit_status = establish_arrays_for_pitchwork(dz))<0) {
  5950. print_messages_and_close_sndfiles(exit_status,is_launched,dz);
  5951. return(FAILED);
  5952. }
  5953. dz->fsil_ratio = FSILENCE_RATIO/20.0;
  5954. dz->fsil_ratio = pow(10.0,dz->fsil_ratio);
  5955. dz->fsil_ratio = 1.0/dz->fsil_ratio;
  5956. initrand48(); // Possibly needed
  5957. if((exit_status = setup_ring(dz))<0) // Establish ring used for pitch-detection
  5958. return(exit_status);
  5959. return FINISHED;
  5960. }
  5961. /***************************** ESTABLISH_ARRAYS_FOR_PITCHWORK *************************/
  5962. int establish_arrays_for_pitchwork(dataptr dz)
  5963. {
  5964. int i;
  5965. if((dz->parray[P_PRETOTAMP] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
  5966. sprintf(errstr,"INSUFFICIENT MEMORY for amp totalling array.\n");
  5967. return(MEMORY_ERROR);
  5968. }
  5969. if(dz->mode == F_SYLABTROF)
  5970. return(FINISHED);
  5971. if((dz->parray[RUNNINGAVRG] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
  5972. sprintf(errstr,"INSUFFICIENT MEMORY for running averages array.\n");
  5973. return(MEMORY_ERROR);
  5974. }
  5975. if((dz->parray[RUNAVGDURS] = (double *)malloc(dz->wlength * sizeof(double)))==NULL) {
  5976. sprintf(errstr,"INSUFFICIENT MEMORY for running average durations array.\n");
  5977. return(MEMORY_ERROR);
  5978. }
  5979. if((dz->lparray[AVSTT] = (int *)malloc(dz->wlength * sizeof(int)))==NULL) {
  5980. sprintf(errstr,"INSUFFICIENT MEMORY for running averages window-position array.\n");
  5981. return(MEMORY_ERROR);
  5982. }
  5983. //RWD NOV97 quick solution to unassigned value somewhere in spec pitch!
  5984. for(i = 0; i < dz->wlength;i++)
  5985. dz->parray[P_PRETOTAMP][i] = 0.0;
  5986. if((dz->pitches = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
  5987. sprintf(errstr,"INSUFFICIENT MEMORY for pitches array.\n");
  5988. return(MEMORY_ERROR);
  5989. }
  5990. if(dz->mode == F_PQUANT || dz->mode == F_PCHRAND) {
  5991. if((dz->pitches2 = (float *)malloc(dz->wlength * sizeof(float)))==NULL) {
  5992. sprintf(errstr,"INSUFFICIENT MEMORY for pitches array.\n");
  5993. return(MEMORY_ERROR);
  5994. }
  5995. }
  5996. return(FINISHED);
  5997. }
  5998. /****************************** SPECPITCH *******************************
  5999. *
  6000. * (1) Ignore partials below low limit of pitch.
  6001. * (2) If this channel data is louder than any existing piece of data in ring.
  6002. * (Ring data is ordered loudness-wise)...
  6003. * (3) If this freq is too close to an existing frequency..
  6004. * (4) and if it is louder than that existing frequency data..
  6005. * (5) Substitute in in the ring.
  6006. * (6) Otherwise, (its a new frq) insert it into the ring.
  6007. */
  6008. int specpitch(int inner_lpcnt,double *target, dataptr dz)
  6009. {
  6010. int exit_status;
  6011. int vc, pitchcc;
  6012. chvptr here, there, *partials;
  6013. float minamp, newfrq;
  6014. double loudest_partial_frq, nextloudest_partial_frq, lo_loud_partial, hi_loud_partial, thepitch;
  6015. if((partials = (chvptr *)malloc(FMAXIMI * sizeof(chvptr)))==NULL) {
  6016. sprintf(errstr,"INSUFFICIENT MEMORY for partials array.\n");
  6017. return(MEMORY_ERROR);
  6018. }
  6019. if((exit_status = initialise_ring_vals(FMAXIMI,-1.0,dz))<0)
  6020. return(exit_status);
  6021. for(vc=0;vc<dz->wanted;vc+=2) {
  6022. here = dz->ringhead;
  6023. if(dz->flbufptr[0][FREQ] > VOICELO) { /* 1 */
  6024. do {
  6025. if(dz->flbufptr[0][AMPP] > here->val) { /* 2 */
  6026. if((exit_status = close_to_frq_already_in_ring(&there,(double)dz->flbufptr[0][FREQ],dz))<0)
  6027. return(exit_status);
  6028. if(exit_status==TRUE) {
  6029. if(dz->flbufptr[0][AMPP] > there->val) { /* 4 */
  6030. if((exit_status = substitute_in_ring(vc,here,there,dz))<0) /* 5 */
  6031. return(exit_status);
  6032. }
  6033. } else { /* 6 */
  6034. if((exit_status = insert_in_ring(vc,here,dz))<0)
  6035. return(exit_status);
  6036. }
  6037. break;
  6038. }
  6039. } while((here = here->next)!=dz->ringhead);
  6040. }
  6041. }
  6042. loudest_partial_frq = dz->flbufptr[0][dz->ringhead->loc + 1];
  6043. nextloudest_partial_frq = dz->flbufptr[0][dz->ringhead->next->loc + 1];
  6044. if(loudest_partial_frq < nextloudest_partial_frq) {
  6045. lo_loud_partial = loudest_partial_frq;
  6046. hi_loud_partial = nextloudest_partial_frq;
  6047. } else {
  6048. lo_loud_partial = nextloudest_partial_frq;
  6049. hi_loud_partial = loudest_partial_frq;
  6050. }
  6051. if((exit_status = put_ring_frqs_in_ascending_order(&partials,&minamp,dz))<0)
  6052. return(exit_status);
  6053. if((exit_status = found_pitch(partials,lo_loud_partial,hi_loud_partial,minamp,&thepitch,dz))<0)
  6054. return(exit_status);
  6055. if(exit_status==TRUE) {
  6056. if((exit_status = locate_channel_of_pitch(inner_lpcnt,(float)thepitch,&pitchcc,dz))<0)
  6057. return(exit_status);
  6058. if((exit_status = find_fundamental((float)thepitch,*target,pitchcc,&newfrq,dz))<0)
  6059. return(exit_status);
  6060. *target = (newfrq + *target)/2.0; // target pitch is a running average
  6061. dz->pitches[dz->total_windows] = (float)thepitch;
  6062. } else
  6063. dz->pitches[dz->total_windows] = (float)NOT_PITCH;
  6064. if((exit_status = smooth_spurious_octave_leaps(dz->total_windows,minamp,dz))<0)
  6065. return(exit_status);
  6066. return FINISHED;
  6067. }
  6068. /**************************** CLOSE_TO_FRQ_ALREADY_IN_RING *******************************/
  6069. int close_to_frq_already_in_ring(chvptr *there,double frq1,dataptr dz)
  6070. {
  6071. double frq2, frqratio;
  6072. *there = dz->ringhead;
  6073. do {
  6074. if((*there)->val > 0.0) {
  6075. frq2 = dz->flbufptr[0][(*there)->loc + 1];
  6076. if(frq1 > frq2)
  6077. frqratio = frq1/frq2;
  6078. else
  6079. frqratio = frq2/frq1;
  6080. if(frqratio < EIGHT_OVER_SEVEN)
  6081. return(TRUE);
  6082. }
  6083. } while((*there = (*there)->next) != dz->ringhead);
  6084. return(FALSE);
  6085. }
  6086. /******************************* SUBSITUTE_IN_RING **********************/
  6087. int substitute_in_ring(int vc,chvptr here,chvptr there,dataptr dz)
  6088. {
  6089. chvptr spare, previous;
  6090. if(here!=there) {
  6091. if(there==dz->ringhead) {
  6092. sprintf(errstr,"IMPOSSIBLE! in substitute_in_ring()\n");
  6093. return(PROGRAM_ERROR);
  6094. }
  6095. spare = there;
  6096. there->next->last = there->last; /* SPLICE REDUNDANT STRUCT FROM RING */
  6097. there->last->next = there->next;
  6098. previous = here->last;
  6099. previous->next = spare; /* SPLICE ITS ADDRESS-SPACE BACK INTO RING */
  6100. spare->last = previous; /* IMMEDIATELY BEFORE HERE */
  6101. here->last = spare;
  6102. spare->next = here;
  6103. if(here==dz->ringhead) /* IF HERE IS RINGHEAD, MOVE RINGHEAD */
  6104. dz->ringhead = spare;
  6105. here = spare; /* POINT TO INSERT LOCATION */
  6106. }
  6107. here->val = dz->flbufptr[0][AMPP]; /* IF here==there */
  6108. here->loc = vc; /* THIS WRITES OVER VAL IN EXISTING RING LOCATION */
  6109. return(FINISHED);
  6110. }
  6111. /*************************** INSERT_IN_RING ***************************/
  6112. int insert_in_ring(int vc, chvptr here, dataptr dz)
  6113. {
  6114. chvptr previous, newend, spare;
  6115. if(here==dz->ringhead) {
  6116. dz->ringhead = dz->ringhead->last;
  6117. spare = dz->ringhead;
  6118. } else {
  6119. if(here==dz->ringhead->last)
  6120. spare = here;
  6121. else {
  6122. spare = dz->ringhead->last;
  6123. newend = dz->ringhead->last->last; /* cut ENDADR (spare) out of ring */
  6124. dz->ringhead->last = newend;
  6125. newend->next = dz->ringhead;
  6126. previous = here->last;
  6127. here->last = spare; /* reuse spare address at new loc by */
  6128. spare->next = here; /* inserting it back into ring before HERE */
  6129. previous->next = spare;
  6130. spare->last = previous;
  6131. }
  6132. }
  6133. spare->val = dz->flbufptr[0][vc]; /* Store new val in spare ring location */
  6134. spare->loc = vc;
  6135. return(FINISHED);
  6136. }
  6137. /************************** PUT_RING_FRQS_IN_ASCENDING_ORDER **********************/
  6138. int put_ring_frqs_in_ascending_order(chvptr **partials,float *minamp,dataptr dz)
  6139. {
  6140. int k;
  6141. chvptr start, ggot, here = dz->ringhead;
  6142. float minpitch;
  6143. *minamp = (float)MAXFLOAT;
  6144. for(k=0;k<FMAXIMI;k++) {
  6145. if((*minamp = min(dz->flbufptr[0][here->loc],*minamp))>=(float)MAXFLOAT) {
  6146. sprintf(errstr,"Problem with amplitude out of range: put_ring_frqs_in_ascending_order()\n");
  6147. return(PROGRAM_ERROR);
  6148. }
  6149. (here->loc)++; /* CHANGE RING TO POINT TO FRQS, not AMPS */
  6150. here->val = dz->flbufptr[0][here->loc];
  6151. here = here->next;
  6152. }
  6153. here = dz->ringhead;
  6154. minpitch = dz->flbufptr[0][here->loc];
  6155. for(k=1;k<FMAXIMI;k++) {
  6156. start = ggot = here;
  6157. while((here = here->next)!=start) { /* Find lowest frq */
  6158. if(dz->flbufptr[0][here->loc] < minpitch) {
  6159. minpitch = dz->flbufptr[0][here->loc];
  6160. ggot = here;
  6161. }
  6162. }
  6163. (*partials)[k-1] = ggot; /* Save its address */
  6164. here = ggot->next; /* Move to next ring site */
  6165. minpitch = dz->flbufptr[0][here->loc]; /* Preset minfrq to val there */
  6166. ggot->last->next = here; /* Unlink ringsite ggot */
  6167. here->last = ggot->last;
  6168. }
  6169. (*partials)[k-1] = here; /* Remaining ringsite is maximum */
  6170. here = dz->ringhead = (*partials)[0]; /* Reconstruct ring */
  6171. for(k=1;k<FMAXIMI;k++) {
  6172. here->next = (*partials)[k];
  6173. (*partials)[k]->last = here;
  6174. here = here->next;
  6175. }
  6176. here->next = dz->ringhead; /* Close up ring */
  6177. dz->ringhead->last = here;
  6178. return(FINISHED);
  6179. }
  6180. /****************************** FOUND_PITCH **************************/
  6181. int found_pitch(chvptr *partials,double lo_loud_partial,double hi_loud_partial,float minamp,double *thepitch,dataptr dz)
  6182. {
  6183. int n, m, k, maximi_less_one = MAXIMUM_PARTIAL - 1, endd = 0;
  6184. double whole_number_ratio, comparison_frq;
  6185. for(n=1;n<maximi_less_one;n++) {
  6186. for(m=n+1;m<MAXIMUM_PARTIAL;m++) { /* NOV 7 */
  6187. whole_number_ratio = (double)m/(double)n;
  6188. comparison_frq = lo_loud_partial * whole_number_ratio;
  6189. if(equivalent_pitches(comparison_frq,hi_loud_partial,dz))
  6190. endd = (MAXIMUM_PARTIAL/m) * n; /* explanation at foot of file */
  6191. else if(comparison_frq > hi_loud_partial)
  6192. break;
  6193. for(k=n;k<=endd;k+=n) {
  6194. *thepitch = lo_loud_partial/(double)k;
  6195. if(*thepitch>FPICH_HILM)
  6196. continue;
  6197. if(*thepitch<SPEC_MINFRQ)
  6198. break;
  6199. if(is_peak_at(*thepitch,0,minamp,dz)){
  6200. if(enough_partials_are_harmonics(partials,*thepitch,dz))
  6201. return TRUE;
  6202. }
  6203. }
  6204. }
  6205. }
  6206. return(FALSE);
  6207. }
  6208. /************************ SMOOTH_SPURIOUS_OCTAVE_LEAPS ***************************/
  6209. int smooth_spurious_octave_leaps(int pitchno,float minamp,dataptr dz)
  6210. {
  6211. double thispitch = dz->pitches[pitchno];
  6212. double startpitch, lastpitch;
  6213. int k = 0;
  6214. if(pitchno<=0)
  6215. return(FINISHED);
  6216. lastpitch = dz->pitches[pitchno-1];
  6217. if(lastpitch > SPEC_MINFRQ && thispitch > SPEC_MINFRQ) { /* OCTAVE ADJ HERE */
  6218. if(thispitch > lastpitch) { /* OCTAVE ADJ FORWARDS */
  6219. startpitch = thispitch;
  6220. while(thispitch/lastpitch > ALMOST_TWO)
  6221. thispitch /= 2.0;
  6222. if(thispitch!=startpitch) {
  6223. if(thispitch < SPEC_MINFRQ)
  6224. return(FINISHED);
  6225. if(is_peak_at(thispitch,0L,minamp,dz))
  6226. dz->pitches[pitchno] = (float)thispitch;
  6227. else
  6228. dz->pitches[pitchno] = (float)startpitch;
  6229. }
  6230. return(FINISHED);
  6231. } else {
  6232. while(pitchno>=1) { /* OCTAVE ADJ BCKWARDS */
  6233. k++;
  6234. if((thispitch = dz->pitches[pitchno--])<SPEC_MINFRQ)
  6235. return(FINISHED);
  6236. if((lastpitch = dz->pitches[pitchno])<SPEC_MINFRQ)
  6237. return(FINISHED);
  6238. startpitch = lastpitch;
  6239. while(lastpitch/thispitch > ALMOST_TWO)
  6240. lastpitch /= 2.0;
  6241. if(lastpitch!=startpitch) {
  6242. if(lastpitch < SPEC_MINFRQ)
  6243. return(FINISHED);
  6244. if(is_peak_at(lastpitch,k,minamp,dz))
  6245. dz->pitches[pitchno] = (float)lastpitch;
  6246. else
  6247. dz->pitches[pitchno] = (float)startpitch;
  6248. }
  6249. }
  6250. }
  6251. }
  6252. return(FINISHED);
  6253. }
  6254. /*************************** IS_PEAK_AT ***************************/
  6255. int is_peak_at(double frq,int window_offset,float minamp,dataptr dz)
  6256. {
  6257. float *thisbuf;
  6258. int cc, vc, searchtop, searchbot;
  6259. if(window_offset) { /* BAKTRAK ALONG BIGBUF, IF NESS */
  6260. thisbuf = dz->flbufptr[0] - (window_offset * dz->wanted);
  6261. if((int)thisbuf < 0 || thisbuf < dz->bigfbuf || thisbuf >= dz->flbufptr[2])
  6262. return(FALSE);
  6263. } else
  6264. thisbuf = dz->flbufptr[0];
  6265. cc = (int)((frq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  6266. searchtop = min(dz->clength,cc + FCHANSCAN + 1);
  6267. searchbot = max(0,cc - FCHANSCAN);
  6268. for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
  6269. if(!equivalent_pitches((double)thisbuf[vc+1],frq,dz)) {
  6270. continue;
  6271. }
  6272. if(thisbuf[vc] < minamp * FPEAK_LIMIT)
  6273. continue;
  6274. if(local_peak(cc,frq,thisbuf,dz))
  6275. return TRUE;
  6276. }
  6277. return FALSE;
  6278. }
  6279. /***************************** LOCAL_PEAK **************************/
  6280. int local_peak(int thiscc,double frq, float *thisbuf, dataptr dz)
  6281. {
  6282. int thisvc = thiscc * 2;
  6283. int cc, vc, searchtop, searchbot;
  6284. double frqtop = frq * SEMITONE_INTERVAL;
  6285. double frqbot = frq / SEMITONE_INTERVAL;
  6286. searchtop = (int)((frqtop + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  6287. searchtop = min(dz->clength,searchtop + PEAKSCAN + 1);
  6288. searchbot = (int)((frqbot + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  6289. searchbot = max(0,searchbot - PEAKSCAN);
  6290. for(cc = searchbot ,vc = searchbot*2; cc < searchtop; cc++, vc += 2) {
  6291. if(thisbuf[thisvc] < thisbuf[vc])
  6292. return(FALSE);
  6293. }
  6294. return(TRUE);
  6295. }
  6296. /**************************** ENOUGH_PARTIALS_ARE_HARMONICS *************************/
  6297. int enough_partials_are_harmonics(chvptr *partials,double thepitch,dataptr dz)
  6298. {
  6299. int n, good_match = 0;
  6300. double thisfrq;
  6301. for(n=0;n<FMAXIMI;n++) {
  6302. if((thisfrq = dz->flbufptr[0][partials[n]->loc]) < thepitch)
  6303. continue;
  6304. if(is_equivalent_pitch(thisfrq,thepitch,dz)){
  6305. if(++good_match >= GOOD_MATCH)
  6306. return TRUE;
  6307. }
  6308. }
  6309. return FALSE;
  6310. }
  6311. /**************************** IS_EQUIVALENT_PITCH *************************/
  6312. int is_equivalent_pitch(double frq1,double frq2,dataptr dz)
  6313. {
  6314. double ratio = frq1/frq2;
  6315. int iratio = round(ratio);
  6316. double intvl;
  6317. ratio = frq1/frq2;
  6318. iratio = round(ratio);
  6319. if(ratio > iratio)
  6320. intvl = ratio/(double)iratio;
  6321. else
  6322. intvl = (double)iratio/ratio;
  6323. if(intvl > SEMITONE_INTERVAL)
  6324. return(FALSE);
  6325. return(TRUE);
  6326. }
  6327. /**************************** IS_ABOVE_EQUIVALENT_PITCH *************************/
  6328. int is_above_equivalent_pitch(double frq1,double frq2,dataptr dz)
  6329. {
  6330. double ratio = frq1/frq2;
  6331. int iratio = round(ratio);
  6332. double intvl;
  6333. ratio = frq1/frq2;
  6334. iratio = round(ratio);
  6335. intvl = ratio/(double)iratio;
  6336. if(intvl > SEMITONE_INTERVAL)
  6337. return(FALSE);
  6338. return(TRUE);
  6339. }
  6340. // SMOOTHING AND VERIFYING PITCH
  6341. /***************************** TIDY_UP_PITCH_DATA ***********************/
  6342. int tidy_up_pitch_data(dataptr dz)
  6343. {
  6344. int exit_status;
  6345. if((exit_status = anti_noise_smoothing(dz->wlength,dz->pitches,dz->frametime))<0)
  6346. return(exit_status);
  6347. if((exit_status = continuity_smoothing(dz))<0)
  6348. return(exit_status);
  6349. if((exit_status = mark_zeros_in_pitchdata(dz))<0)
  6350. return(exit_status);
  6351. if((exit_status = eliminate_blips_in_pitch_data(dz))<0)
  6352. return(exit_status);
  6353. if((exit_status = interpolate_pitch(dz))<0)
  6354. return exit_status;
  6355. return pitch_found(dz);
  6356. }
  6357. /**************************** PITCH_FOUND ****************************/
  6358. int pitch_found(dataptr dz)
  6359. {
  6360. int n;
  6361. for(n=0;n<dz->wlength;n++) {
  6362. if(dz->pitches[n] > NOT_PITCH)
  6363. return(FINISHED);
  6364. }
  6365. sprintf(errstr,"No valid pitch found.\n");
  6366. return(GOAL_FAILED);
  6367. }
  6368. /********************************** MARK_ZEROS_IN_PITCHDATA ************************
  6369. *
  6370. * Disregard data on windows which are FSILENCE_RATIO below maximum level.
  6371. */
  6372. int mark_zeros_in_pitchdata(dataptr dz)
  6373. {
  6374. int n;
  6375. double maxlevel = 0.0, minlevel;
  6376. for(n=0;n<dz->wlength;n++) {
  6377. if(dz->parray[P_PRETOTAMP][n] > maxlevel)
  6378. maxlevel = dz->parray[P_PRETOTAMP][n];
  6379. }
  6380. minlevel = maxlevel * dz->fsil_ratio;
  6381. for(n=0;n<dz->wlength;n++) {
  6382. if(dz->parray[P_PRETOTAMP][n] < minlevel)
  6383. dz->pitches[n] = (float)NOT_SOUND;
  6384. }
  6385. return(FINISHED);
  6386. }
  6387. /************************** ELIMINATE_BLIPS_IN_PITCH_DATA ****************************
  6388. *
  6389. * (1) Eliminate any group of FBLIPLEN pitched windows, bracketed by
  6390. * unpitched windows, as unreliable data.
  6391. */
  6392. int eliminate_blips_in_pitch_data(dataptr dz)
  6393. {
  6394. int n, m, k, wlength_less_bliplen;
  6395. int OK = 1;
  6396. wlength_less_bliplen = dz->wlength - FBLIPLEN;
  6397. for(n=1;n<wlength_less_bliplen;n++) {
  6398. if(dz->pitches[n] > 0.0) {
  6399. if(dz->pitches[n-1] < 0.0) {
  6400. for(k = 1; k <= FBLIPLEN; k++) {
  6401. if(dz->pitches[n+k] < 0.0) {
  6402. for(m=0;m<k;m++)
  6403. dz->pitches[n+m] = (float)NOT_PITCH;
  6404. n += k;
  6405. continue;
  6406. }
  6407. }
  6408. }
  6409. }
  6410. }
  6411. n = wlength_less_bliplen;
  6412. if((dz->pitches[n] > 0.0) && (dz->pitches[n-1] < 0.0)) {
  6413. for(k = 1; k < FBLIPLEN; k++) {
  6414. if(dz->pitches[n+k] < 0.0)
  6415. OK = 0;
  6416. break;
  6417. }
  6418. }
  6419. if(!OK) {
  6420. for(n=wlength_less_bliplen;n<dz->wlength;n++)
  6421. dz->pitches[n] = (float)NOT_PITCH;
  6422. }
  6423. return(FINISHED);
  6424. }
  6425. /********************** ANTI_NOISE_SMOOTHING *********************/
  6426. int anti_noise_smoothing(int wlength,float *pitches,float frametime)
  6427. {
  6428. char *smooth;
  6429. double max_pglide;
  6430. int n;
  6431. if(wlength < FMIN_SMOOTH_SET + 1)
  6432. return(FINISHED);
  6433. max_pglide = pow(2.0,FMAX_GLISRATE) * frametime;
  6434. if((smooth = (char *)malloc((size_t)wlength))==NULL) {
  6435. sprintf(errstr,"aINSUFFICIENT MEMORY for smoothing array.\n");
  6436. return(MEMORY_ERROR);
  6437. }
  6438. for(n=1;n<wlength-1;n++)
  6439. smooth[n] = (char)is_smooth_from_both_sides(n,max_pglide,pitches);
  6440. smooth[0] = (char)is_initialpitch_smooth(smooth,max_pglide,pitches);
  6441. smooth[wlength-1] = (char)is_finalpitch_smooth(smooth,max_pglide,wlength,pitches);
  6442. for(n=FMIN_SMOOTH_SET-1;n<wlength;n++) {
  6443. if(!smooth[n])
  6444. smooth[n] = (char)is_smooth_from_before(n,smooth,max_pglide,pitches);
  6445. }
  6446. for(n=0;n<=wlength-FMIN_SMOOTH_SET;n++) {
  6447. if(!smooth[n])
  6448. smooth[n] = (char)is_smooth_from_after(n,smooth,max_pglide,pitches);
  6449. }
  6450. test_glitch_sets(smooth,max_pglide,wlength,pitches);
  6451. remove_unsmooth_pitches(smooth,wlength,pitches);
  6452. free(smooth);
  6453. return(FINISHED);
  6454. }
  6455. /********************** IS_SMOOTH_FROM_BOTH_SIDES *********************
  6456. *
  6457. * verify a pitch if it has continuity with the pitches on either side.
  6458. */
  6459. int is_smooth_from_both_sides(int n,double max_pglide,float *pitches)
  6460. {
  6461. float thispitch, pitch_before, pitch_after;
  6462. double pre_interval, post_interval;
  6463. if((thispitch = pitches[n]) < FLTERR)
  6464. return FALSE;
  6465. if((pitch_before = pitches[n-1]) < FLTERR)
  6466. return FALSE;
  6467. if((pitch_after = pitches[n+1]) < FLTERR)
  6468. return FALSE;
  6469. pre_interval = pitch_before/thispitch;
  6470. if(pre_interval < 1.0)
  6471. pre_interval = 1.0/pre_interval;
  6472. post_interval = pitch_after/thispitch;
  6473. if(post_interval < 1.0)
  6474. post_interval = 1.0/post_interval;
  6475. if(pre_interval > max_pglide
  6476. || post_interval > max_pglide)
  6477. return FALSE;
  6478. return TRUE;
  6479. }
  6480. /********************** IS_INITIALPITCH_SMOOTH *********************
  6481. *
  6482. * verify first pitch if it has continuity with an ensuing verified pitch.
  6483. */
  6484. int is_initialpitch_smooth(char *smooth,double max_pglide,float *pitches)
  6485. {
  6486. float thispitch;
  6487. int n;
  6488. double post_interval;
  6489. if((thispitch = pitches[0]) < FLTERR)
  6490. return FALSE;
  6491. for(n=1;n < FMIN_SMOOTH_SET;n++) {
  6492. if(smooth[n]) {
  6493. post_interval = pitches[n]/pitches[0];
  6494. if(post_interval < 1.0)
  6495. post_interval = 1.0/post_interval;
  6496. if(post_interval <= pow(max_pglide,(double)n))
  6497. return TRUE;
  6498. }
  6499. }
  6500. return(FALSE);
  6501. }
  6502. /********************** IS_FINALPITCH_SMOOTH *********************
  6503. *
  6504. * verify final pitch if it has continuity with a preceding verified pitch.
  6505. */
  6506. int is_finalpitch_smooth(char *smooth,double max_pglide,int wlength,float *pitches)
  6507. {
  6508. float thispitch;
  6509. double pre_interval;
  6510. int n;
  6511. int last = wlength - 1;
  6512. if((thispitch = pitches[last]) < FLTERR)
  6513. return FALSE;
  6514. for(n=1;n < FMIN_SMOOTH_SET;n++) {
  6515. if(smooth[last-n]) {
  6516. pre_interval = pitches[last-n]/pitches[last];
  6517. if(pre_interval < 1.0)
  6518. pre_interval = 1.0/pre_interval;
  6519. if(pre_interval <= pow(max_pglide,(double)n))
  6520. return TRUE;
  6521. }
  6522. }
  6523. return(FALSE);
  6524. }
  6525. /********************** IS_SMOOTH_FROM_BEFORE *********************
  6526. *
  6527. * verify a pitch which has continuity with a preceding set of verified pitches.
  6528. */
  6529. int is_smooth_from_before(int n,char *smooth,double max_pglide,float *pitches)
  6530. {
  6531. float thispitch, pitch_before;
  6532. double pre_interval;
  6533. int m;
  6534. if((thispitch = pitches[n]) < FLTERR)
  6535. return FALSE;
  6536. for(m=1;m<FMIN_SMOOTH_SET;m++) { /* If there are (FMIN_SMOOTH_SET-1) smooth pitches before */
  6537. if(!smooth[n-m])
  6538. return(FALSE);
  6539. }
  6540. pitch_before = pitches[n-1]; /* Test the interval with the previous pitch */
  6541. pre_interval = pitch_before/thispitch;
  6542. if(pre_interval < 1.0)
  6543. pre_interval = 1.0/pre_interval;
  6544. if(pre_interval > max_pglide)
  6545. return FALSE; /* And if it's acceptably smooth */
  6546. return TRUE; /* mark this pitch as smooth also */
  6547. }
  6548. /********************** IS_SMOOTH_FROM_AFTER *********************
  6549. *
  6550. * verify a pitch which has continuity with a following set of verified pitches.
  6551. */
  6552. int is_smooth_from_after(int n,char *smooth,double max_pglide,float *pitches)
  6553. {
  6554. float thispitch, pitch_after;
  6555. double post_interval;
  6556. int m;
  6557. if((thispitch = pitches[n]) < FLTERR)
  6558. return FALSE;
  6559. for(m=1;m<FMIN_SMOOTH_SET;m++) { /* If there are (FMIN_SMOOTH_SET-1) smooth pitches after */
  6560. if(!smooth[n+m])
  6561. return(FALSE);
  6562. }
  6563. pitch_after = pitches[n+1]; /* Test the interval with the next pitch */
  6564. post_interval = pitch_after/thispitch;
  6565. if(post_interval < 1.0)
  6566. post_interval = 1.0/post_interval;
  6567. if(post_interval > max_pglide)
  6568. return FALSE; /* And if it's acceptably smooth */
  6569. return TRUE; /* mark this pitch as smooth also */
  6570. }
  6571. /********************** TEST_GLITCH_SETS *********************
  6572. *
  6573. * This function looks for any sets of values that appear to be glitches
  6574. * amongst the real pitch data.
  6575. * It is possible some items are REAL pitch data isolated BETWEEN short glitches.
  6576. * This function checks for these cases.
  6577. */
  6578. int test_glitch_sets(char *smooth,double max_pglide,int wlength,float *pitches)
  6579. {
  6580. int exit_status;
  6581. int gotglitch = FALSE;
  6582. int n, gltchend, gltchstart = 0;
  6583. for(n=0;n<wlength;n++) {
  6584. if(gotglitch) { /* if inside a glitch */
  6585. if(smooth[n]) { /* if reached its end, mark the end, then process the glitch */
  6586. gltchend = n;
  6587. if((exit_status = test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches))<0)
  6588. return(exit_status);
  6589. if((exit_status = test_glitch_backwards(gltchstart,gltchend,smooth,max_pglide,wlength,pitches))<0)
  6590. return(exit_status);
  6591. gotglitch = 0;
  6592. }
  6593. } else { /* look for a glitch and mark its start */
  6594. if(!smooth[n]) {
  6595. gotglitch = 1;
  6596. gltchstart = n;
  6597. }
  6598. }
  6599. }
  6600. if(gotglitch) { /* if inside a glitch at end of data, process glitch */
  6601. gltchend = n;
  6602. test_glitch_forwards(gltchstart,gltchend,smooth,max_pglide,pitches);
  6603. }
  6604. return(FINISHED);
  6605. }
  6606. /********************* REMOVE_UNSMOOTH_PITCHES ***********************
  6607. *
  6608. * delete all pitches which have no verified continuity with surrounding pitches.
  6609. */
  6610. void remove_unsmooth_pitches(char *smooth,int wlength,float *pitches)
  6611. {
  6612. int n;
  6613. for(n=0;n<wlength;n++) {
  6614. if(!smooth[n])
  6615. pitches[n] = (float)NOT_PITCH;
  6616. }
  6617. }
  6618. /********************** TEST_GLITCH_FORWARDS *********************
  6619. *
  6620. * searching from start of glitch, look for isolated true pitches
  6621. * amongst glitch data.
  6622. */
  6623. #define LAST_SMOOTH_NOT_SET (-1)
  6624. int test_glitch_forwards(int gltchstart,int gltchend,char *smooth,double max_pglide,float *pitches)
  6625. {
  6626. int n, glcnt;
  6627. int last_smooth, previous;
  6628. double pre_interval;
  6629. if((previous = gltchstart - 1) < 0)
  6630. return FINISHED;
  6631. if(pitches[previous] < FLTERR) {
  6632. sprintf(errstr,"Error in previous smoothing logic: test_glitch_forwards()\n");
  6633. return(PROGRAM_ERROR);
  6634. }
  6635. last_smooth = previous;
  6636. n = gltchstart+1; /* setup params for local search of glitch */
  6637. glcnt = 1;
  6638. while(n < gltchend) { /* look through the glitch */
  6639. if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
  6640. pre_interval = pitches[n]/pitches[previous];
  6641. if(pre_interval < 1.0)
  6642. pre_interval = 1.0/pre_interval; /* compare against previous verified pitch */
  6643. if(pre_interval <= pow(max_pglide,(double)(n-previous))) {
  6644. smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
  6645. last_smooth = n;
  6646. }
  6647. }
  6648. n++; /* Once more than a max-glitch-set has been scanned */
  6649. /* or the end of the entire glitch is reached */
  6650. if(++glcnt >= FMIN_SMOOTH_SET || n >= gltchend) {
  6651. if(last_smooth == previous)
  6652. break; /* If no new verifiable pitch found, give up */
  6653. previous = last_smooth;
  6654. n = last_smooth + 1; /* Otherwise start a new local search from newly verified pitch */
  6655. glcnt = 1;
  6656. }
  6657. }
  6658. return(FINISHED);
  6659. }
  6660. /********************** TEST_GLITCH_BACKWARDS *********************
  6661. *
  6662. * searching from end of glitch, look for isolated true pitches
  6663. * amongst glitch data.
  6664. */
  6665. int test_glitch_backwards(int gltchstart,int gltchend,char *smooth,double max_pglide,int wlength,float *pitches)
  6666. {
  6667. int n, glcnt, next, next_smooth;
  6668. double post_interval;
  6669. if((next = gltchend) >= wlength)
  6670. return FINISHED;
  6671. if(pitches[next] < FLTERR) {
  6672. sprintf(errstr,"Error in previous smoothing logic: test_glitch_backwards()\n");
  6673. return(PROGRAM_ERROR);
  6674. }
  6675. next_smooth = next;
  6676. n = gltchend-2; /* setup params for local search of glitch */
  6677. glcnt = 1;
  6678. while(n >= gltchstart) { /* look through the glitch */
  6679. if(pitches[n] > FLTERR) { /* if glitch location holds a true pitch */
  6680. post_interval = pitches[n]/pitches[next];
  6681. if(post_interval < 1.0)
  6682. post_interval = 1.0/post_interval; /* compare against previous verified pitch */
  6683. if(post_interval <= pow(max_pglide,(double)(next - n))) {
  6684. smooth[n] = TRUE; /* if comparable: mark this pitch as verified */
  6685. next_smooth = n;
  6686. }
  6687. }
  6688. n--; /* Once more than a max-glitch-set has been scanned */
  6689. /* or the start of the entire glitch is reached */
  6690. if(++glcnt >= FMIN_SMOOTH_SET || n < gltchstart) {
  6691. if(next_smooth == next)
  6692. break; /* If no new verifiable pitch found, give up */
  6693. next = next_smooth;
  6694. n = next_smooth - 1;
  6695. glcnt = 1; /* Otherwise start a new local search */
  6696. }
  6697. }
  6698. return(FINISHED);
  6699. }
  6700. //////////////////////////////////
  6701. // INTERPOLATING PITCH //
  6702. //////////////////////////////////
  6703. /**************************** INTERPOLATE_PITCH ***************************/
  6704. #define TRUE_UNPITCHED -3
  6705. #define SILENCE_BRACKETED 1
  6706. #define PITCH_BRACKETED 2
  6707. #define PITCH_ONSET 3
  6708. #define PITCH_ENDING 4
  6709. int interpolate_pitch(dataptr dz)
  6710. {
  6711. int exit_status;
  6712. int pitchno, unpitchstart = 0, unpitchcnt = 0, k;
  6713. int min_unpitch_windows = (int)round(TOO_SHORT_UNPICH/dz->frametime);
  6714. int unpitched_eventtype = 0;
  6715. // Eliminate too short unpitched-bloks appropriately to their context //
  6716. if(dz->retain_unpitched_data_for_deletion) {
  6717. for(pitchno=0;pitchno<dz->wlength;pitchno++) {
  6718. if(flteq((double)dz->pitches[pitchno],NOT_SOUND)) { // SILENCE
  6719. if(unpitchcnt == 0)
  6720. continue; // If there's an unpitched blok, it's followed by silence
  6721. if(unpitchcnt > min_unpitch_windows) { // If unpitched is long enough
  6722. for(k = unpitchstart;k < pitchno;k++) // mark as truly unpitched
  6723. dz->pitches[k] = TRUE_UNPITCHED; // Else
  6724. } else {
  6725. for(k = unpitchstart;k < pitchno;k++)
  6726. dz->pitches[k] = NOT_SOUND; // Treat as silence (will be zeroed)
  6727. }
  6728. unpitchcnt = 0;
  6729. } else if(dz->pitches[pitchno] > FSPEC_MINFRQ) { // PITCHED
  6730. if(unpitchcnt == 0)
  6731. continue;
  6732. if(unpitchcnt > min_unpitch_windows) { // If unpitched is long enough
  6733. for(k = unpitchstart;k < pitchno;k++) // mark as truly unpitched
  6734. dz->pitches[k] = TRUE_UNPITCHED; // Else
  6735. } else {
  6736. // Unpitched blok followed by pitch
  6737. if (unpitchstart > 0 && (dz->pitches[unpitchstart-1] > FSPEC_MINFRQ))
  6738. unpitched_eventtype = PITCH_BRACKETED; // Bracketed by pitch
  6739. else // OR
  6740. unpitched_eventtype = PITCH_ONSET; // introduces pitched material (material before unpitched must have been silence)
  6741. switch(unpitched_eventtype) {
  6742. case(PITCH_ONSET):
  6743. for(k = unpitchstart;k < pitchno;k++)
  6744. dz->pitches[k] = NOT_SOUND; // Treat as silence (will be zeroed)
  6745. break;
  6746. case(PITCH_BRACKETED): // will be interpolated to give a pitch value
  6747. break;
  6748. }
  6749. }
  6750. unpitchcnt = 0;
  6751. } else { // UNPITCHED
  6752. if(unpitchcnt == 0)
  6753. unpitchstart = pitchno;
  6754. unpitchcnt++;
  6755. }
  6756. }
  6757. // Deal with any unpitched blok at end of file
  6758. if(unpitchcnt > 0) {
  6759. if(unpitchcnt > min_unpitch_windows) { // If unpitched is long enough
  6760. for(k = unpitchstart;k < dz->wlength;k++) // mark as truly unpitched
  6761. dz->pitches[k] = TRUE_UNPITCHED;
  6762. } else { // Else
  6763. if (unpitchstart > 0 && (dz->pitches[unpitchstart-1] >= FSPEC_MINFRQ))
  6764. unpitched_eventtype = PITCH_ENDING; // Preceded by pitch
  6765. else // OR
  6766. unpitched_eventtype = SILENCE_BRACKETED; // material before unpitched must have been silence
  6767. switch(unpitched_eventtype) {
  6768. case(SILENCE_BRACKETED):
  6769. for(k = unpitchstart;k < pitchno;k++)
  6770. dz->pitches[k] = NOT_SOUND; // Treat as silence (will be zeroed)
  6771. break;
  6772. case(PITCH_ENDING): // will be interpolated to give a pitch value
  6773. break;
  6774. }
  6775. }
  6776. }
  6777. }
  6778. // We now have a file with (1) PITCH, (2) Interpolatable stretches of NON_PICH, (3) TRUE_UNPITCHED and (4) NOT_SOUND
  6779. for(pitchno=0;pitchno<dz->wlength;pitchno++) {
  6780. if(dz->pitches[pitchno] < FSPEC_MINFRQ) {
  6781. if(dz->retain_unpitched_data_for_deletion && dz->pitches[pitchno] <= NOT_SOUND)
  6782. continue;
  6783. if((exit_status = do_interpolating(&pitchno,dz->retain_unpitched_data_for_deletion,dz))<0)
  6784. return(exit_status);
  6785. }
  6786. }
  6787. // 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)
  6788. if(dz->retain_unpitched_data_for_deletion) {
  6789. for(pitchno=0;pitchno<dz->wlength;pitchno++) {
  6790. if(flteq((double)dz->pitches[pitchno],TRUE_UNPITCHED))
  6791. dz->pitches[pitchno] = NOT_PITCH;
  6792. }
  6793. }
  6794. return(FINISHED);
  6795. }
  6796. /****************************** DO_INTERPOLATING *************************/
  6797. int do_interpolating(int *pitchno,int retain_unpitched_data_for_deletion,dataptr dz)
  6798. {
  6799. int act_type = FMID_PITCH;
  6800. int start = *pitchno, m;
  6801. double startpitch, endpitch, thispitch, lastpitch, pstep;
  6802. if(*pitchno==0L) // Window is at start of file
  6803. act_type = FFIRST_PITCH;
  6804. while(dz->pitches[*pitchno] < FSPEC_MINFRQ) { // If window is unpitched, advance until we find a pitched window
  6805. if(++(*pitchno)>=dz->wlength) { // IF we reach end of file without finding pitched window
  6806. if(act_type == FFIRST_PITCH) // if we started search at file start,
  6807. act_type = FNO_PITCH; // there is no pitch to find in the file.
  6808. else
  6809. act_type = FEND_PITCH; // otherwise this is an unpitched blok at file end
  6810. break;
  6811. }
  6812. }
  6813. if(act_type==FMID_PITCH) { // As default, this is an unpitched blok in mid file
  6814. m = start-1; // search backwards for a valid pitch
  6815. while(dz->pitches[m] < FSPEC_MINFRQ) {
  6816. if(--m <= 0) { // and if we reach file start without finding one
  6817. act_type = FFIRST_PITCH; // this is an unpitched blok at file start
  6818. break;
  6819. }
  6820. }
  6821. start = m;
  6822. }
  6823. switch(act_type) {
  6824. case(FMID_PITCH):
  6825. startpitch = hz_to_pitchheight((double)dz->pitches[start-1]);
  6826. endpitch = hz_to_pitchheight((double)dz->pitches[*pitchno]);
  6827. pstep = (endpitch - startpitch)/(double)((*pitchno) - (start - 1));
  6828. lastpitch = startpitch;
  6829. for(m=start;m<*pitchno;m++) { // Interp pitch across unpitched seg
  6830. thispitch = lastpitch + pstep;
  6831. if(!(retain_unpitched_data_for_deletion && dz->pitches[m]<=NOT_SOUND)) // i.e. If we are retaining truly non-pitched material and silence
  6832. dz->pitches[m] = (float)pitchheight_to_hz(thispitch); // and this is such material, don't interp!!
  6833. lastpitch = thispitch;
  6834. }
  6835. break;
  6836. case(FFIRST_PITCH):
  6837. for(m=0;m<*pitchno;m++) { // Extend first clear pitch back to start
  6838. if(!(retain_unpitched_data_for_deletion && (dz->pitches[m]<=NOT_SOUND)))
  6839. dz->pitches[m] = dz->pitches[*pitchno];
  6840. }
  6841. break;
  6842. case(FEND_PITCH): // Extend last clear pitch on to end
  6843. for(m=start;m<*pitchno;m++) {
  6844. if(!(retain_unpitched_data_for_deletion && (dz->pitches[m]<=NOT_SOUND)))
  6845. dz->pitches[m] = dz->pitches[start-1];
  6846. }
  6847. break;
  6848. case(FNO_PITCH):
  6849. sprintf(errstr,"No valid pitch found.\n");
  6850. return(GOAL_FAILED);
  6851. }
  6852. (*pitchno)--; // set next interpolation to start at end of this interpolated block
  6853. return(FINISHED);
  6854. }
  6855. /***************************** HZ_TO_PITCHHEIGHT *******************************
  6856. *
  6857. * Real pitch is 12 * log2(frq/basis_frq).
  6858. *
  6859. * BUT (with a little help from the Feynman lectures!!)
  6860. * (1) The basis_frq is arbitrary, and cancels out, so let it be 1.0.
  6861. i.e. pitch1 = 12 * log2(frq1/basis_frq) = 12 * (log2(frq1) - log2(basis_frq));
  6862. pitch2 = 12 * log2(frq2/basis_frq) = 12 * (log2(frq2) - log2(basis_frq));
  6863. pitch1 - pitch2 = 12 * (log2(frq1) - log2(frq2)) = 12 * log2(frq1/frq2);
  6864. * (2) Finding the difference of 2 log2() numbers, interpolating and
  6865. * reconverting to pow(2.0,...) is no different to doing same
  6866. * calculation to base e.
  6867. * (3) The (12 *) is also a cancellable factor in all this.
  6868. * So pitch_height serves the same function as pitch in these calculations!!
  6869. */
  6870. double hz_to_pitchheight(double frqq)
  6871. {
  6872. return log(frqq);
  6873. }
  6874. /***************************** PITCHHEIGHT_TO_HZ *******************************/
  6875. double pitchheight_to_hz(double pitch_height)
  6876. {
  6877. return exp(pitch_height);
  6878. }
  6879. /************************* LOCATE CHANNEL OF FUNDAMENTAL *********************/
  6880. int locate_channel_of_fundamental(int inner_lpcnt,float *fundfrq, int *newcc,dataptr dz)
  6881. {
  6882. double srchbot, srchtop, fundamp, ferror, frq, subfrq = HUGE, top;
  6883. int cc, vc, subchan = 0;
  6884. *fundfrq = (float)dz->pitches[inner_lpcnt];
  6885. if(*fundfrq < 0.0)
  6886. return FINISHED;
  6887. srchbot = *fundfrq * SEVEN_OVER_EIGHT;
  6888. srchtop = *fundfrq * EIGHT_OVER_SEVEN;
  6889. ferror = HUGE;
  6890. if(inner_lpcnt == 0) { // Window zero has no meaningful data
  6891. frq = 0.0; // search using centre and top frqs of frq bins
  6892. top = dz->halfchwidth;
  6893. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  6894. if(top < srchbot) {
  6895. subfrq = frq; // Remember chan-frq and number of the channel before fundamental (should be) found
  6896. subchan = cc;
  6897. } else if(frq < srchtop) { // For any channel in range, find channel-centre closest to fundamental
  6898. if(fabs(*fundfrq - frq) < ferror) {
  6899. ferror = fabs(*fundfrq - frq);
  6900. *newcc = cc;
  6901. }
  6902. } else if(ferror == HUGE) { // If no frequencies within range of fundamental (should be impossible!!), keep closest
  6903. if(fabs(frq - *fundfrq) < fabs(*fundfrq - subfrq))
  6904. *newcc = cc; // If chan-frq above searched-for range is closer than one below, use its channel
  6905. else
  6906. *newcc = subchan; // else use channel below
  6907. break;
  6908. }
  6909. frq += dz->chwidth;
  6910. top += dz->chwidth;
  6911. }
  6912. } else { // Normal case
  6913. fundamp = -HUGE;
  6914. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  6915. frq = dz->flbufptr[0][FREQ];
  6916. if(frq < srchbot) {
  6917. subfrq = frq; // Remember frq and channo in channel before fundamental (should be) found
  6918. subchan = cc;
  6919. } else if(frq < srchtop) {
  6920. if(dz->flbufptr[0][AMPP] > fundamp) { // If (frqs near) fundamental found, find loudest occurence
  6921. fundamp = dz->flbufptr[0][AMPP];
  6922. *newcc = cc;
  6923. }
  6924. } else if(fundamp == -HUGE) { // If no frequencies within range of fundamental, keep closest in frq
  6925. if(subfrq == HUGE)
  6926. *newcc = cc; // If there is no subfrq, use the frq in chan above range
  6927. if(fabs(frq - *fundfrq) < fabs(*fundfrq - subfrq))
  6928. *newcc = cc; // If frq above is closer than one below, use its channel
  6929. else
  6930. *newcc = subchan; // else use channel below
  6931. break;
  6932. }
  6933. }
  6934. }
  6935. return FINISHED;
  6936. }
  6937. /************************* LOCATE_CHANNEL_OF_PITCH *********************/
  6938. int locate_channel_of_pitch(int inner_lpcnt,float thepitch, int *newcc,dataptr dz)
  6939. {
  6940. double srchbot, srchtop, fundamp, ferror, frq, subfrq = HUGE, top;
  6941. int cc, vc, subchan = 0;
  6942. if(thepitch < 0.0) {
  6943. sprintf(errstr,"This process needs interpolated pitch data: the extracted pitchdata still has pitch-zeros or silence-zeros.\n");
  6944. return USER_ERROR;
  6945. }
  6946. srchbot = thepitch * SEVEN_OVER_EIGHT;
  6947. srchtop = thepitch * EIGHT_OVER_SEVEN;
  6948. ferror = HUGE;
  6949. if(inner_lpcnt == 0) { // Window zero has no meaningful data
  6950. frq = 0.0; // search using centre and top frqs of frq bins
  6951. top = dz->halfchwidth;
  6952. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) { //RWD was vc+2
  6953. if(top < srchbot) {
  6954. subfrq = frq; // Remember chan-frq and number of the channel before fundamental (should be) found
  6955. subchan = cc;
  6956. } else if(frq < srchtop) { // For any channel in range, find channel-centre closest to fundamental
  6957. if(fabs(thepitch - frq) < ferror) {
  6958. ferror = fabs(thepitch - frq);
  6959. *newcc = cc;
  6960. }
  6961. } else if(ferror == HUGE) { // If no frequencies within range of fundamental (should be impossible!!), keep closest
  6962. if(fabs(frq - thepitch) < fabs(thepitch - subfrq))
  6963. *newcc = cc; // If chan-frq above searched-for range is closer than one below, use its channel
  6964. else
  6965. *newcc = subchan; // else use channel below
  6966. break;
  6967. }
  6968. frq += dz->chwidth;
  6969. top += dz->chwidth;
  6970. }
  6971. } else { // Normal case
  6972. fundamp = -HUGE;
  6973. for(cc=0,vc=0;cc<dz->clength;cc++,vc+=2) {
  6974. frq = dz->flbufptr[0][FREQ];
  6975. if(frq < srchbot) {
  6976. subfrq = frq; // Remember frq and channo in channel before fundamental (should be) found
  6977. subchan = cc;
  6978. } else if(frq < srchtop) {
  6979. if(dz->flbufptr[0][AMPP] > fundamp) { // If (frqs near) fundamental found, find loudest occurence
  6980. fundamp = dz->flbufptr[0][AMPP];
  6981. *newcc = cc;
  6982. }
  6983. } else if(fundamp == -HUGE) { // If no frequencies within range of fundamental, keep closest in frq
  6984. if(subfrq == HUGE)
  6985. *newcc = cc; // If there is no subfrq, use the frq in chan above range
  6986. if(fabs(frq - thepitch) < fabs(thepitch - subfrq))
  6987. *newcc = cc; // If frq above is closer than one below, use its channel
  6988. else
  6989. *newcc = subchan; // else use channel below
  6990. break;
  6991. }
  6992. }
  6993. }
  6994. return FINISHED;
  6995. }
  6996. /************************************ CONTINUITY_SMOOTHING ***************************/
  6997. int continuity_smoothing(dataptr dz)
  6998. {
  6999. double *running_average = dz->parray[RUNNINGAVRG];
  7000. double *runavdur = dz->parray[RUNAVGDURS];
  7001. int *avstart = dz->lparray[AVSTT];
  7002. int runavcnt = 0, lastrunavcnt, n, maxavg, ahead, behind, bracketed, thisbracketed;
  7003. double ratio, maxtime, bracketdur = 0.0;
  7004. int done;
  7005. memset((char *)running_average,0,dz->wlength * sizeof(double));
  7006. memset((char *)runavdur,0,dz->wlength * sizeof(double));
  7007. memset((char *)avstart,0,dz->wlength * sizeof(int));
  7008. // FIND BLOCKS WHOSE RUNNING AVERAGES DIFFER
  7009. for(n = 0; n < dz->wlength;n++) {
  7010. if(dz->pitches[n] < 0.0) // Don't weigh time of non-pitch areas
  7011. continue;
  7012. if(running_average[runavcnt] == 0.0) { // First running average will not have a start value
  7013. avstart[runavcnt] = n;
  7014. running_average[runavcnt] = dz->pitches[n];
  7015. } else {
  7016. if(dz->pitches[n] > running_average[runavcnt])
  7017. ratio = dz->pitches[n]/running_average[runavcnt];
  7018. else
  7019. ratio = running_average[runavcnt]/dz->pitches[n];
  7020. if(ratio < ALMOST_TWO) // If next pitch is close to running-average, continue to average, and sum duration
  7021. running_average[runavcnt] = (running_average[runavcnt] + dz->pitches[n])/2;
  7022. else { // IF not, start a new average
  7023. runavcnt++;
  7024. avstart[runavcnt] = n;
  7025. running_average[runavcnt] = dz->pitches[n];
  7026. }
  7027. }
  7028. runavdur[runavcnt] += dz->frametime;
  7029. }
  7030. runavcnt++;
  7031. if(runavcnt < 2)
  7032. return FINISHED;
  7033. lastrunavcnt = runavcnt;
  7034. do {
  7035. // FIND THE LONGEST BLOCK (Aread with no apparent pitch are not counted)
  7036. maxtime = 0.0;
  7037. maxavg = 0;
  7038. for(n = 0;n<runavcnt;n++) {
  7039. if(runavdur[n] > maxtime) {
  7040. maxtime = runavdur[n];
  7041. maxavg = n;
  7042. }
  7043. }
  7044. // WORKING OUTWARDS FROM THE LONGEST BLOCK, ELIMINATE BLOCKS WHICH ARE SUDDENLY DIFFERENT, FOR TOO SHORT A TIME
  7045. if(maxavg < runavcnt-2) {
  7046. for(n = maxavg; n < runavcnt;n++) { // working upwards from the most persistent average
  7047. ahead = n+2; // find if the bracketing bloks of the next blok have similar average
  7048. bracketed = n+1;
  7049. if(ahead >= runavcnt)
  7050. break;
  7051. bracketdur = 0.0;
  7052. done = 0;
  7053. if(running_average[n] > running_average[ahead])
  7054. ratio = running_average[n]/running_average[ahead];
  7055. else
  7056. ratio = running_average[ahead]/running_average[n];
  7057. bracketdur = runavdur[bracketed];
  7058. if(ratio < ALMOST_TWO) { // If 2 bracketing averages are similar
  7059. if (runavdur[bracketed] < TOO_SHORT_PICH) { // & intervening block is short
  7060. averages_smooth(bracketed,n,runavcnt,dz); // Smooth the intervening block
  7061. n++; // and skip over the intervening (smoothed) block, and continue
  7062. } else
  7063. continue; // But if not short, proceed normally along the array
  7064. } else { // If 2 bracketing averages are not similar,
  7065. while(runavdur[bracketed]<TOO_SHORT_PICH) { // we have at least 3 contiguous but different averages
  7066. ahead++; // proceed to wider bracket
  7067. bracketed++;
  7068. if(ahead >= runavcnt) { // until we find a matching pair of bracketing averages
  7069. done = 1;
  7070. break;
  7071. }
  7072. bracketdur += runavdur[bracketed];
  7073. if(bracketdur > TOO_SHORT_PICH) // If total duration of bracketed items no longer short, go back to outer loop
  7074. break;
  7075. if(running_average[n] > running_average[ahead])
  7076. ratio = running_average[n]/running_average[ahead];
  7077. else
  7078. ratio = running_average[ahead]/running_average[n];
  7079. if(ratio < ALMOST_TWO) { // If we finally find a valid outer bracket
  7080. // (Total duration of things within bracket is still very short)
  7081. for(thisbracketed = n+1;thisbracketed < ahead;thisbracketed++)
  7082. averages_smooth(thisbracketed,n,runavcnt,dz); // Smooth ALL the intervening block
  7083. n += (ahead-n)-1; // We want to advance to "ahead": loop will force advance of 1.
  7084. break;
  7085. } // so advance here by distance from n to ahead (= ahead-n) minus 1
  7086. } // Otherwise we have found yet another non-matching block
  7087. } // continue to assemble bracketed items
  7088. if(done)
  7089. break;
  7090. }
  7091. } else // Either maxavg is at the v. end (so no end to check)
  7092. n = maxavg; // Or it is at the penultimate position, so need to check last blok
  7093. // CHECK THE LAST BLOCK, IF NOT ALREADY CHECKED
  7094. if(n == runavcnt-2) {
  7095. bracketed = n+1;
  7096. if(running_average[bracketed] > running_average[n])
  7097. ratio = running_average[bracketed]/running_average[n];
  7098. else
  7099. ratio = running_average[n]/running_average[bracketed];
  7100. if(ratio < ALMOST_TWO && runavdur[bracketed] < TOO_SHORT_PICH)
  7101. averages_smooth(bracketed,n,runavcnt,dz);
  7102. }
  7103. // NOW PROCEED BACKWARDS FROM LONGEST BLOK
  7104. if(maxavg > 1) {
  7105. for(n = maxavg; n >= 0; n--) { // working backwards from the most persistent average
  7106. behind = n-2;
  7107. bracketed = n-1;
  7108. if(behind < 0)
  7109. break;
  7110. bracketdur = 0.0;
  7111. done = 0;
  7112. if(running_average[n] > running_average[behind])
  7113. ratio = running_average[n]/running_average[behind];
  7114. else
  7115. ratio = running_average[behind]/running_average[n];
  7116. if(ratio < ALMOST_TWO) { // If 2 bracketing averages are similar
  7117. if(runavdur[bracketed] < TOO_SHORT_PICH) { // & intervening block is short
  7118. averages_smooth(bracketed,n,runavcnt,dz); // Smooth the intervening block
  7119. n--; // and skip over the intervening (smoothed) block, and continue
  7120. } else
  7121. continue; // But if not short, proceed normally along the array
  7122. } else { // If 2 bracketing averages are not similar,
  7123. while(runavdur[bracketed]<TOO_SHORT_PICH) { // we have at least 3 contiguous but different averages
  7124. behind--; // proceed to wider bracket
  7125. bracketed--;
  7126. if(behind <= 0) { // until we find a matching pair of bracketing averages
  7127. done = 1;
  7128. break;
  7129. }
  7130. bracketdur += runavdur[bracketed];
  7131. if(bracketdur > TOO_SHORT_PICH) // If total duration of bracketed items no loner short, go back to outer loop
  7132. break;
  7133. if(running_average[n] > running_average[behind])
  7134. ratio = running_average[n]/running_average[behind];
  7135. else
  7136. ratio = running_average[behind]/running_average[n];
  7137. if(ratio < ALMOST_TWO) { // If we finally find a valid outer bracket
  7138. // (Total duration of things within bracket is still very short)
  7139. for(thisbracketed = n-1;thisbracketed > behind;thisbracketed--)
  7140. averages_smooth(thisbracketed,n,runavcnt,dz); // Smooth ALL the intervening block
  7141. n -= (n-behind)-1; // We want to regress to "behind": loop will force regress of 1, so advance here by "ahead-1"
  7142. break; // so regress here by distance from n to behind (= n-behind) minus 1
  7143. } // ang go back to outer loop
  7144. } // Otherwise we have found yet another non-matching block
  7145. } // continue to assemble bracketed items
  7146. if(done)
  7147. break;
  7148. }
  7149. }
  7150. // CHECK THE FIRST BLOCK IF NESS
  7151. if(n == 1) {
  7152. bracketed = 0;
  7153. if(running_average[bracketed] > running_average[n])
  7154. ratio = running_average[bracketed]/running_average[n];
  7155. else
  7156. ratio = running_average[n]/running_average[bracketed];
  7157. if(ratio < ALMOST_TWO && runavdur[bracketed] < TOO_SHORT_PICH)
  7158. averages_smooth(bracketed,n,runavcnt,dz);
  7159. }
  7160. // NOW RECURSIVELY SMOOTH ON NEW VALUES UNTIL NO MORE SMOOTHING POSSIBLE
  7161. memset((char *)running_average,0,dz->wlength * sizeof(double));
  7162. memset((char *)runavdur,0,dz->wlength * sizeof(double));
  7163. memset((char *)avstart,0,dz->wlength * sizeof(int));
  7164. lastrunavcnt = runavcnt;
  7165. runavcnt = 0;
  7166. for(n = 0; n < dz->wlength;n++) {
  7167. if(dz->pitches[n] < 0.0)
  7168. continue;
  7169. if(running_average[runavcnt] == 0.0) {
  7170. avstart[runavcnt] = n;
  7171. running_average[runavcnt] = dz->pitches[n];
  7172. } else {
  7173. if(dz->pitches[n] > running_average[runavcnt])
  7174. ratio = dz->pitches[n]/running_average[runavcnt];
  7175. else
  7176. ratio = running_average[runavcnt]/dz->pitches[n];
  7177. if(ratio < ALMOST_TWO)
  7178. running_average[runavcnt] = (running_average[runavcnt] + dz->pitches[n])/2;
  7179. else {
  7180. runavcnt++;
  7181. avstart[runavcnt] = n;
  7182. running_average[runavcnt] = dz->pitches[n];
  7183. }
  7184. }
  7185. runavdur[runavcnt] += dz->frametime;
  7186. }
  7187. runavcnt++;
  7188. if(runavcnt < 2)
  7189. break;
  7190. } while(runavcnt < lastrunavcnt);
  7191. return FINISHED;
  7192. }
  7193. /************************************ AVERAGES_SMOOTH ***************************/
  7194. int averages_smooth(int bracketed,int bracket,int runavcnt,dataptr dz)
  7195. {
  7196. double new_running_average, ratio, newratio;
  7197. int k, avend;
  7198. int *avstart = dz->lparray[AVSTT];
  7199. double *running_average = dz->parray[RUNNINGAVRG];
  7200. if(bracketed+1 == runavcnt)
  7201. avend = dz->wlength;
  7202. else
  7203. avend = avstart[bracketed+1];
  7204. if(running_average[bracketed] > running_average[bracket]) { // If bracketed material too high
  7205. do {
  7206. new_running_average = 0.0;
  7207. for(k = avstart[bracketed]; k < avend;k++) {
  7208. if(dz->pitches[k] > 0.0) { // 8va transpose-down the bracketed material
  7209. dz->pitches[k] /= 2.0;
  7210. if(new_running_average == 0.0)
  7211. new_running_average = dz->pitches[k];
  7212. else
  7213. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7214. }
  7215. }
  7216. if(new_running_average > running_average[bracket]) { // If we're still higher than the goal
  7217. ratio = new_running_average/running_average[bracket];
  7218. if(ratio < ALMOST_TWO) { // But we're now in acceptable range
  7219. new_running_average = 0.0;
  7220. for(k = avstart[bracketed]; k < avend;k++) { // try the next 8va down
  7221. if(dz->pitches[k] > 0.0) {
  7222. dz->pitches[k] /= 2.0;
  7223. if(new_running_average == 0.0)
  7224. new_running_average = dz->pitches[k];
  7225. else
  7226. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7227. }
  7228. }
  7229. if(new_running_average > running_average[bracket])
  7230. newratio = new_running_average/running_average[bracket];
  7231. else
  7232. newratio = running_average[bracket]/new_running_average;
  7233. if(newratio > ratio) { // if the new material is further away from the goal than originally
  7234. for(k = avstart[bracketed]; k < avend;k++) {
  7235. if(dz->pitches[k] > 0.0)
  7236. dz->pitches[k] *= 2.0; // restore to original 8va
  7237. }
  7238. }
  7239. break; // Now quit with new pitch
  7240. }
  7241. } else // Else we.re mow lower than the goal, so at nearest
  7242. break; //
  7243. } while(ratio > ALMOST_TWO);
  7244. } else { // Else bracketed material is too low
  7245. do {
  7246. new_running_average = 0.0;
  7247. for(k = avstart[bracketed]; k < avend;k++) {
  7248. if(dz->pitches[k] > 0.0) {
  7249. dz->pitches[k] *= 2.0; // 8va transpose-up the bracketed material
  7250. if(new_running_average == 0.0)
  7251. new_running_average = dz->pitches[k];
  7252. else
  7253. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7254. }
  7255. }
  7256. if(new_running_average < running_average[bracket]) { // If we're still lower than the goal
  7257. ratio = running_average[bracket]/new_running_average;
  7258. if(ratio < ALMOST_TWO) { // But we're now in acceptable range
  7259. new_running_average = 0.0;
  7260. for(k = avstart[bracketed]; k < avend;k++) {
  7261. if(dz->pitches[k] > 0.0) {
  7262. dz->pitches[k] *= 2.0; // try the next 8va up
  7263. if(new_running_average == 0.0)
  7264. new_running_average = dz->pitches[k];
  7265. else
  7266. new_running_average = (new_running_average + dz->pitches[k])/2.0;
  7267. }
  7268. }
  7269. if(new_running_average > running_average[bracket])
  7270. newratio = new_running_average/running_average[bracket];
  7271. else
  7272. newratio = running_average[bracket]/new_running_average;
  7273. if(newratio > ratio) { // if the new material is further away from the goal than originally
  7274. for(k = avstart[bracketed]; k < avend;k++) {
  7275. if(dz->pitches[k] > 0.0)
  7276. dz->pitches[k] /= 2.0; // restore to original 8va
  7277. }
  7278. }
  7279. break;
  7280. }
  7281. } else // Else we.re now higher than the goal, so at nearest
  7282. break;
  7283. } while(ratio > ALMOST_TWO);
  7284. }
  7285. return FINISHED;
  7286. }
  7287. /************************************ EXCLUDE_NON_HARMONICS ***************************/
  7288. int exclude_non_harmonics(dataptr dz)
  7289. {
  7290. dz->xclude_nonh = 0;
  7291. switch(dz->mode) {
  7292. case(F_NARROW): if(dz->vflag[NRW_XNH]) dz->xclude_nonh = 1; break;
  7293. case(F_SQUEEZE): if(dz->vflag[SQZ_XNH]) dz->xclude_nonh = 1; break;
  7294. // case(F_NEGATE): if(dz->vflag[NEG_XNH]) dz->xclude_nonh = 1; break;
  7295. case(F_MOVE): if(dz->vflag[MOV_XNH]) dz->xclude_nonh = 1; break;
  7296. case(F_MOVE2): if(dz->vflag[MOV2_XNH]) dz->xclude_nonh = 1; break;
  7297. case(F_INVERT): if(dz->vflag[INVERT_XNH]) dz->xclude_nonh = 1; break;
  7298. case(F_ROTATE): if(dz->vflag[ROTATE_XNH]) dz->xclude_nonh = 1; break;
  7299. case(F_SUPPRESS): if(dz->vflag[SUPPRESS_XNH]) dz->xclude_nonh = 1; break;
  7300. case(F_ARPEG): // fall thro
  7301. case(F_OCTSHIFT): // fall thro
  7302. case(F_TRANS): // fall thro
  7303. case(F_FRQSHIFT): // fall thro
  7304. case(F_RESPACE): // fall thro
  7305. case(F_PINVERT): // fall thro
  7306. case(F_PEXAGG): // fall thro
  7307. case(F_PQUANT): // fall thro
  7308. case(F_PCHRAND): // fall thro
  7309. case(F_RAND): if(dz->vflag[RECOLOR_XNH]) dz->xclude_nonh = 1; break;
  7310. }
  7311. if(dz->xclude_nonh) {
  7312. if((dz->fptr[HMNICBOUNDS] = (float *)malloc(10 * sizeof(float)))==NULL) {
  7313. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonic peak boundaries.\n");
  7314. return(MEMORY_ERROR);
  7315. }
  7316. }
  7317. return FINISHED;
  7318. }
  7319. /************************************ ZERO_NON_PARTIALS ***************************/
  7320. #define ABOVE_NYQUIST 0
  7321. int channel_holds_harmonic(float the_fundamental,float frq,int cc,int *top_hno,dataptr dz)
  7322. {
  7323. float *harmbounds = dz->fptr[HMNICBOUNDS], this_harmonic_frq, lobnd, upbnd;
  7324. int mid = 3, bndpairscnt = 5, boundscnt = bndpairscnt * 2;
  7325. int k, hno, lower, upper;
  7326. if(cc == 0) {
  7327. hno = 1;
  7328. for(k=0,lower=0,upper=1;k < bndpairscnt;k++,lower+=2,upper+=2) {
  7329. this_harmonic_frq = (float)(the_fundamental * hno); // lo1 hi1 lo2 hi2 lo3 hi3 lo4 hi4 lo5 hi5
  7330. lobnd = (float)(this_harmonic_frq * SEMITONE_DOWN); // | | | | | | | | | |
  7331. upbnd = (float)(this_harmonic_frq * SEMITONE_INTERVAL); // 0 1 2 3 4 5 6 7 8 9
  7332. harmbounds[lower] = lobnd;
  7333. harmbounds[upper] = upbnd;
  7334. hno++;
  7335. }
  7336. *top_hno = bndpairscnt;
  7337. }
  7338. if(frq > harmbounds[mid])
  7339. if(shufflup_harmonics_bounds(top_hno,the_fundamental,boundscnt,dz)== ABOVE_NYQUIST)
  7340. return 0;
  7341. for(k=0,hno = 1,lower=0,upper=1;k < bndpairscnt;k++,hno++,lower+=2,upper+=2) {
  7342. if(frq > harmbounds[lower]) {
  7343. if(frq < harmbounds[upper]) // Within frq bounds of a harmonic
  7344. return 1;
  7345. if(lower < boundscnt - 2) {
  7346. if(frq < harmbounds[lower+2]) { // Outside frq bounds of a harmonic
  7347. return 0;
  7348. }
  7349. } else { // Outside top harmonic boUnds
  7350. if(shufflup_harmonics_bounds(top_hno,the_fundamental,boundscnt,dz)==ABOVE_NYQUIST)
  7351. return 0; // get next harmonic, and its bounds
  7352. k--;
  7353. lower -= 2;
  7354. upper -= 2;
  7355. }
  7356. }
  7357. }
  7358. return 0; // SHOULD BE "NOT REACHED" !!!
  7359. }
  7360. /************************************ SHUFFLUP_HARMONICS_BOUNDS ***************************/
  7361. int shufflup_harmonics_bounds(int *top_hno,float the_fundamental,int boundscnt,dataptr dz)
  7362. {
  7363. float *harmbounds = dz->fptr[HMNICBOUNDS];
  7364. float this_harmonic_frq, lobnd, upbnd;
  7365. int k;
  7366. (*top_hno)++; // lo2 hi2 lo3 hi3 lo4 hi4 lo5 hi5
  7367. this_harmonic_frq = (float)the_fundamental * (*top_hno);// | | | | | | | | | |
  7368. for(k=2;k < boundscnt;k++) // 0 1 2 3 4 5 6 7 8 9
  7369. harmbounds[k-2] = harmbounds[k];
  7370. if(harmbounds[0] > dz->nyquist)
  7371. return ABOVE_NYQUIST;
  7372. lobnd = (float)(this_harmonic_frq * SEMITONE_DOWN); // Insert boundaries of next harmonic
  7373. upbnd = (float)(this_harmonic_frq * SEMITONE_INTERVAL); // lo2 hi2 lo3 hi3 lo4 hi4 lo5 hi5 lo6 hi6
  7374. harmbounds[boundscnt - 2] = lobnd; // | | | | | | | | | |
  7375. harmbounds[boundscnt - 1] = upbnd; // 0 1 2 3 4 5 6 7 8 9
  7376. return 1;
  7377. }
  7378. /***************************************** INITIALISE_CONTOURENV ***************************/
  7379. int initialise_contourenv(int *contourcnt,int contour_halfbands_per_step,dataptr dz)
  7380. {
  7381. int arraycnt, contourbands;
  7382. double frqstep, thisfrq, nextfrq;
  7383. int k = 0;
  7384. contourbands = (int)ceil(dz->clength / (contour_halfbands_per_step / 2));
  7385. arraycnt = contourbands + 2;
  7386. if((dz->fptr[CONTOURFRQ] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7387. sprintf(errstr,"INSUFFICIENT MEMORY for contour frq array.\n");
  7388. return(MEMORY_ERROR);
  7389. }
  7390. if((dz->fptr[CONTOURPCH] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7391. sprintf(errstr,"INSUFFICIENT MEMORY for contour pitch array.\n");
  7392. return(MEMORY_ERROR);
  7393. }
  7394. /*RWD zero the data */
  7395. memset((char *)dz->fptr[CONTOURPCH],0,arraycnt * sizeof(float));
  7396. if((dz->fptr[CONTOURAMP] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7397. sprintf(errstr,"INSUFFICIENT MEMORY for contour amplitude array.\n");
  7398. return(MEMORY_ERROR);
  7399. }
  7400. if((dz->fptr[CONTOURTOP] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7401. sprintf(errstr,"INSUFFICIENT MEMORY for contour frq limit array.\n");
  7402. return(MEMORY_ERROR);
  7403. }
  7404. if((dz->fptr[CONTOURAMP2] = (float *)malloc((arraycnt) * sizeof(float)))==NULL) {
  7405. sprintf(errstr,"INSUFFICIENT MEMORY for contour amplitude array.\n");
  7406. return(MEMORY_ERROR);
  7407. }
  7408. dz->fptr[CONTOURAMP][0] = (float)0.0;
  7409. dz->fptr[CONTOURFRQ][0] = (float)1.0;
  7410. dz->fptr[CONTOURPCH][0] = (float)log10(dz->fptr[CONTOURFRQ][0]);
  7411. dz->fptr[CONTOURTOP][0] = (float)dz->halfchwidth;
  7412. frqstep = dz->halfchwidth * (double)contour_halfbands_per_step;
  7413. thisfrq = dz->fptr[CONTOURTOP][0];
  7414. k = 1;
  7415. while((nextfrq = thisfrq + frqstep) < dz->nyquist) {
  7416. if(k >= arraycnt) {
  7417. sprintf(errstr,"Formant array too small: when setting the contour frqs\n");
  7418. return(PROGRAM_ERROR);
  7419. }
  7420. dz->fptr[CONTOURFRQ][k] = (float)nextfrq;
  7421. dz->fptr[CONTOURPCH][k] = (float)log10(dz->fptr[CONTOURFRQ][k]);
  7422. dz->fptr[CONTOURTOP][k] = (float)min(dz->nyquist,nextfrq);
  7423. thisfrq = nextfrq;
  7424. k++;
  7425. }
  7426. dz->fptr[CONTOURFRQ][k] = (float)dz->nyquist;
  7427. dz->fptr[CONTOURPCH][k] = (float)log10(dz->nyquist);
  7428. dz->fptr[CONTOURTOP][k] = (float)dz->nyquist;
  7429. dz->fptr[CONTOURAMP][k] = (float)0.0;
  7430. k++;
  7431. *contourcnt = k;
  7432. return(FINISHED);
  7433. }
  7434. /**************************** GETCONTOURAMP *************************/
  7435. int getcontouramp(double *thisamp,int contourcnt,double thisfrq,dataptr dz)
  7436. {
  7437. double pp, ratio, ampdiff;
  7438. float *contourpch = dz->fptr[CONTOURPCH], *contouramp = dz->fptr[CONTOURAMP];
  7439. int z = 1;
  7440. if(thisfrq<0.0) { /* NOT SURE THIS IS CORRECT */
  7441. *thisamp = 0.0; /* SHOULD WE PHASE INVERT & RETURN A -ve AMP ?? */
  7442. return(FINISHED);
  7443. }
  7444. if(thisfrq<=1.0)
  7445. pp = 0.0;
  7446. else
  7447. pp = log10(thisfrq);
  7448. while(contourpch[z] < pp){
  7449. z++;
  7450. /*RWD may need to trap on size of array? */
  7451. if(z == contourcnt - 1)
  7452. break;
  7453. }
  7454. ratio = (pp - contourpch[z-1])/(contourpch[z] - contourpch[z-1]);
  7455. ampdiff = contouramp[z] - contouramp[z-1];
  7456. *thisamp = contouramp[z-1] + (ampdiff * ratio);
  7457. *thisamp = max(0.0,*thisamp);
  7458. return(FINISHED);
  7459. }
  7460. /**************************** GETCONTOURAMP2 *************************/
  7461. int getcontouramp2(double *thisamp,int contourcnt,double thisfrq,dataptr dz)
  7462. {
  7463. double pp, ratio, ampdiff;
  7464. float *contourpch = dz->fptr[CONTOURPCH], *contouramp2 = dz->fptr[CONTOURAMP2];
  7465. int z = 1;
  7466. if(thisfrq<0.0) { /* NOT SURE THIS IS CORRECT */
  7467. *thisamp = 0.0; /* SHOULD WE PHASE INVERT & RETURN A -ve AMP ?? */
  7468. return(FINISHED);
  7469. }
  7470. if(thisfrq<=1.0)
  7471. pp = 0.0;
  7472. else
  7473. pp = log10(thisfrq);
  7474. while(contourpch[z] < pp){
  7475. z++;
  7476. /*RWD may need to trap on size of array? */
  7477. if(z == contourcnt - 1)
  7478. break;
  7479. }
  7480. ratio = (pp - contourpch[z-1])/(contourpch[z] - contourpch[z-1]);
  7481. ampdiff = contouramp2[z] - contouramp2[z-1];
  7482. *thisamp = contouramp2[z-1] + (ampdiff * ratio);
  7483. *thisamp = max(0.0,*thisamp);
  7484. return(FINISHED);
  7485. }
  7486. /*********************** REMEMBER_CONTOURAMP ****************/
  7487. int remember_contouramp(int contourcnt,dataptr dz)
  7488. {
  7489. int n;
  7490. float *contouramp2 = dz->fptr[CONTOURAMP2], *contouramp = dz->fptr[CONTOURAMP];
  7491. if(contouramp2 == NULL) {
  7492. sprintf(errstr,"Contour amp 2nd array has not been mallocd.\n");
  7493. return PROGRAM_ERROR;
  7494. }
  7495. for(n = 0;n < contourcnt;n++)
  7496. contouramp2[n] = contouramp[n];
  7497. return FINISHED;
  7498. }
  7499. /********************** EXTRACT_CONTOUR *******************/
  7500. #define CHAN_SRCHRANGE_F (4)
  7501. int extract_contour(int contourcnt,dataptr dz)
  7502. {
  7503. int n, cc, vc, contourcnt_less_one;
  7504. int botchan, topchan;
  7505. double botfreq, topfreq;
  7506. double bwidth_in_chans;
  7507. float *contouramp = dz->fptr[CONTOURAMP];
  7508. memset((char *)contouramp,0,contourcnt * sizeof(float));
  7509. contourcnt_less_one = contourcnt - 1;
  7510. vc = 0;
  7511. for(n=0;n<contourcnt;n++)
  7512. contouramp[n] = (float)0.0;
  7513. topfreq = 0.0f;
  7514. n = 0;
  7515. while(n < contourcnt_less_one) {
  7516. botfreq = topfreq;
  7517. botchan = (int)((botfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  7518. botchan -= CHAN_SRCHRANGE_F;
  7519. botchan = max(botchan,0);
  7520. topfreq = dz->specenvtop[n];
  7521. topchan = (int)((topfreq + dz->halfchwidth)/dz->chwidth); /* TRUNCATE */
  7522. topchan += CHAN_SRCHRANGE_F;
  7523. topchan = min(topchan,dz->clength);
  7524. for(cc = botchan,vc = botchan * 2; cc < topchan; cc++,vc += 2) {
  7525. if(dz->flbufptr[0][FREQ] >= botfreq && dz->flbufptr[0][FREQ] < topfreq)
  7526. contouramp[n] = (float)(contouramp[n] + dz->flbufptr[0][AMPP]);
  7527. }
  7528. bwidth_in_chans = (double)(topfreq - botfreq)/dz->chwidth;
  7529. contouramp[n] = (float)(contouramp[n]/bwidth_in_chans);
  7530. n++;
  7531. }
  7532. return(FINISHED);
  7533. }
  7534. /************************************ SUPPRESS_HARMONICS ***************************/
  7535. int suppress_harmonics(dataptr dz)
  7536. {
  7537. int suppress_h = 0;
  7538. switch(dz->mode) {
  7539. case(F_MOVE): if(dz->vflag[MOV_KHM]) suppress_h = 1; break;
  7540. case(F_MOVE2): if(dz->vflag[MOV2_KHM]) suppress_h = 1; break;
  7541. // case(F_NEGATE): if(dz->vflag[NEG_KHM]) suppress_h = 1; break;
  7542. case(F_INVERT): if(dz->vflag[INVERT_KHM]) suppress_h = 1; break;
  7543. case(F_NARROW): if(dz->vflag[NRW_KHM]) suppress_h = 1; break;
  7544. case(F_SQUEEZE):if(dz->vflag[SQZ_KHM]) suppress_h = 1; break;
  7545. case(F_ROTATE): if(dz->vflag[ROTATE_KHM]) suppress_h = 1; break;
  7546. }
  7547. if(suppress_h && dz->fptr[HMNICBOUNDS] == NULL) {
  7548. if((dz->fptr[HMNICBOUNDS] = (float *)malloc(10 * sizeof(float)))==NULL) {
  7549. sprintf(errstr,"INSUFFICIENT MEMORY to store harmonic peak boundaries.\n");
  7550. return(MEMORY_ERROR);
  7551. }
  7552. }
  7553. return FINISHED;
  7554. }
  7555. /************************************ TROF_DETECT ***************************/
  7556. int trof_detect(dataptr dz) // DOESN'T WORK will have to do it BY HAND : Need a SLOOM AP TO HELP !!!
  7557. {
  7558. double *level = dz->parray[P_PRETOTAMP];
  7559. double lev, lastlev = 0.0, maxlevel, rise, endtroftime, endtrofgap, maxval;
  7560. double lastpeak, lastlastpeak, pk_to_pre_trof, pk_to_post_trof;
  7561. int n, tim, val, lasttim, lastval, up_cnt = 0, dn_cnt = 0, trofcnt = 0, endtrofat, lasttrofat, thistrofat = 0, thispeak;
  7562. int k;
  7563. double *trof;
  7564. if((trof = (double *)malloc(dz->wlength * 2 * sizeof(float)))==NULL) {
  7565. sprintf(errstr,"INSUFFICIENT MEMORY to store trof times.\n");
  7566. return(MEMORY_ERROR);
  7567. }
  7568. // Establish maximum level
  7569. maxlevel = 0.0;
  7570. for(n=0;n<dz->wlength;n++)
  7571. maxlevel = max(maxlevel,level[n]);
  7572. // Find troughs, ensuring intervening peaks are sufficiently prominent
  7573. lastpeak = -1.0;
  7574. lastlastpeak = -1.0;
  7575. pk_to_pre_trof = -1.0;
  7576. for(n=0;n<dz->wlength;n++) {
  7577. lev = level[n]/maxlevel;
  7578. rise = lev - lastlev;
  7579. if(rise > 0.0) {
  7580. if(dn_cnt > 0) {
  7581. trof[trofcnt++] = dz->frametime * (n-1);
  7582. trof[trofcnt++] = lastlev;
  7583. if(pk_to_pre_trof > 0.0) { // If previous peak-after-a-trof exists
  7584. pk_to_post_trof = lastpeak - trof[trofcnt-1];
  7585. if(lastpeak < dz->fsil_ratio || // If the peak is not absolutely loud enough
  7586. (pk_to_pre_trof < MIN_PEAKTROF_GAP // OR the peak is not high enough above either bracketing trof
  7587. && pk_to_post_trof < MIN_PEAKTROF_GAP)) {
  7588. if(trof[trofcnt-3] < trof[trofcnt-3]) // If previous trof lower than this
  7589. trofcnt -= 2; // overwrite this one
  7590. else { // else
  7591. for(k = trofcnt-2;k< trofcnt;k++) // overwrite last trof
  7592. trof[k-2] = trof[k];
  7593. trofcnt -= 2;
  7594. }
  7595. lastpeak = lastlastpeak; // lastpeak ignored: penultimate peak is now "lastpeak"
  7596. }
  7597. }
  7598. dn_cnt = 0;
  7599. up_cnt = 0;
  7600. }
  7601. up_cnt++;
  7602. } else {
  7603. if(up_cnt > 0) {
  7604. lastlastpeak = lastpeak; // remember this peak and the peak before it
  7605. lastpeak = lastlev; //
  7606. if(trofcnt) // If a prior trof exists, calc ratio of pk to prior trof
  7607. pk_to_pre_trof = lastpeak - trof[trofcnt-1];
  7608. dn_cnt = 0;
  7609. up_cnt = 0;
  7610. }
  7611. dn_cnt++;
  7612. }
  7613. lastlev = lev;
  7614. }
  7615. // Eliminate too close trofs
  7616. lasttim = 0;
  7617. lastval = 1;
  7618. // lasttrofcnt = trofcnt;
  7619. for(tim=2,val=3;tim<trofcnt;tim+=2,val+=2) {
  7620. if(trof[tim] - trof[lasttim] < MIN_SYLLAB_DUR) {
  7621. if(trof[val] <= trof[lastval]) {
  7622. k = tim; // overwrite previous trof
  7623. while(k < trofcnt) {
  7624. trof[k-2] = trof[k];
  7625. k++;
  7626. }
  7627. } else {
  7628. k = tim + 2; // overwrite current trof
  7629. while(k < trofcnt) {
  7630. trof[k-2] = trof[k];
  7631. k++;
  7632. }
  7633. }
  7634. val -= 2;
  7635. tim -= 2;
  7636. trofcnt -= 2;
  7637. } else {
  7638. lasttim += 2;
  7639. lastval += 2;
  7640. }
  7641. }
  7642. endtroftime = 0.0;
  7643. for(n=dz->wlength-1;n>=0;n--) {
  7644. if(level[n] > dz->fsil_ratio) {
  7645. endtroftime = (n+1) * dz->frametime;
  7646. if(endtroftime > 0.0) {
  7647. endtrofgap = endtroftime - trof[trofcnt-2];
  7648. if(endtrofgap > 0.0) {
  7649. endtrofat = n+1;
  7650. lasttrofat = (int)round(trof[trofcnt-2]/dz->frametime);
  7651. maxval = 0.0;
  7652. for(k=lasttrofat;k<endtrofat;k++)
  7653. maxval = max(maxval,level[k]/maxlevel);
  7654. if(maxval - trof[trofcnt-1] < dz->fsil_ratio)
  7655. trof[trofcnt-2] = endtroftime;
  7656. }
  7657. }
  7658. break;
  7659. }
  7660. }
  7661. if(dz->vflag[PKS_ONLY] || dz->vflag[PKS_TROFS]) {
  7662. for(n = 2;n < trofcnt;n+=2) {
  7663. if(n==2)
  7664. lasttrofat = (int)round(trof[n-2]/dz->frametime); // Trof times, converted to window nums
  7665. else
  7666. lasttrofat = thistrofat;
  7667. thistrofat = (int)round(trof[n]/dz->frametime);
  7668. maxlevel = trof[n-1];
  7669. thispeak = lasttrofat;
  7670. for(k = lasttrofat;k < thistrofat;k++) { // Amplitude levels
  7671. if(level[k] > maxlevel) {
  7672. thispeak = k;
  7673. maxlevel = level[k];
  7674. }
  7675. }
  7676. trof[n-1] = thispeak * dz->frametime; // Store peaktimes in place of trof level vals
  7677. }
  7678. if(dz->vflag[PKS_ONLY]) { // Peaks are in odd table locations
  7679. for(n = 1;n < trofcnt-2;n+=2)
  7680. fprintf(dz->fp,"%lf\n",trof[n]);
  7681. } else { // Trofs & peaks are in all locations
  7682. if(trof[0] != 0.0)
  7683. fprintf(dz->fp,"%lf\n",0.0); // Force trof at time zero
  7684. for(n = 0;n < trofcnt-1;n++)
  7685. fprintf(dz->fp,"%lf\n",trof[n]);
  7686. }
  7687. return FINISHED;
  7688. }
  7689. if(trof[0] != 0.0) // Force trof at time zero
  7690. fprintf(dz->fp,"%lf\n",0.0);
  7691. for(n = 0;n < trofcnt;n+=2) // Trof times are in even locations
  7692. fprintf(dz->fp,"%lf\n",trof[n]);
  7693. return FINISHED;
  7694. }
  7695. /************************************ ZERO_SPECTRUM_TOP ***************************/
  7696. void zero_spectrum_top(int cc,dataptr dz)
  7697. {
  7698. int vc = cc * 2;
  7699. for(; cc < dz->clength;cc++, vc+=2)
  7700. dz->flbufptr[0][AMPP] = 0.0f;
  7701. }
  7702. /************************************ FORMANTS_RECOLOR ***************************/
  7703. int formants_recolor(int inner_lpcnt,double *phase,int *up,int arp_param,double minpitch,double maxpitch,int contourcnt,dataptr dz)
  7704. {
  7705. int exit_status, cc, vc, newcc, do_arpegg = 0, nextup = 1, tail = 0, k;
  7706. float the_fundamental, frq, thisfrq, newfrq = 0.0, endamp = 0.0;
  7707. double frqtrans = 1.0, frqshift = 0.0, randomisation = 0.0, rand, incr;
  7708. double nextphase = 0.0, thisamp, origspecamp, newspecamp, vocode_ratio, searchfrqlimit;
  7709. int *isharm = dz->iparray[ISHARM];
  7710. double partial_number_centre, partial_number_foot, partial_number_top, arpegamp = 0.0, pre_amptotal = 0.0, post_amptotal = 0.0;
  7711. 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;
  7712. double lobandbot = 0.0, lobandtop = 0.0, hibandbot = 0.0, hibandtop = 0.0, bwidth = 0.0;
  7713. int is_split = 0, dotopfill = 0;
  7714. // Get window pitch
  7715. the_fundamental = dz->pitches[inner_lpcnt];
  7716. if(the_fundamental < 0.0) { // If unpitched and "silent" windows have been retained & this is one, silence the window
  7717. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc+=2)
  7718. dz->flbufptr[0][AMPP] = 0.0f;
  7719. *up = nextup;
  7720. *phase = nextphase;
  7721. return FINISHED;
  7722. }
  7723. // IF ARPEGGIATING : Calculate the range of the arpeggiation window
  7724. if(dz->brksize[arp_param] || dz->param[arp_param] > 0.0) {
  7725. // IF ARPEGGIATING : precalc nextphase by advancing phase according to arpeggiation-speed
  7726. nextphase = *phase + (dz->param[arp_param] * dz->phasefactor);
  7727. if(nextphase > 1.0) {
  7728. nextup = !(*up);
  7729. nextphase -= 1.0;
  7730. } else
  7731. nextup = *up;
  7732. // & calculate the range of the arpeggiation window
  7733. if(dz->vflag[RECOLOR_DWN])
  7734. partial_number_centre = (1.0 - *phase) * ARPEG_RANGE;
  7735. else if(dz->vflag[RECOLOR_CYC]) {
  7736. if(up)
  7737. partial_number_centre = *phase * ARPEG_RANGE;
  7738. else
  7739. partial_number_centre = (1.0 - *phase) * ARPEG_RANGE;
  7740. } else
  7741. partial_number_centre = *phase * ARPEG_RANGE;
  7742. partial_number_foot = partial_number_centre - ARPEG_WIN_HALFWIDTH;
  7743. partial_number_top = partial_number_centre + ARPEG_WIN_HALFWIDTH;
  7744. if(partial_number_top > ARPEG_RANGE) {
  7745. lower_partial_number_foot = 0.0; // NB partial numbers calculated over range 0 to 7
  7746. lower_partial_number_top = partial_number_top - ARPEG_RANGE; // But need to be in range 1-8 to multiply the fundamental
  7747. upper_partial_number_foot = partial_number_top;
  7748. upper_partial_number_top = ARPEG_RANGE;
  7749. lobandbot = (lower_partial_number_foot + 1.0) * the_fundamental;
  7750. lobandtop = (lower_partial_number_top + 1.0) * the_fundamental;
  7751. hibandbot = (upper_partial_number_foot + 1.0) * the_fundamental;
  7752. hibandtop = (upper_partial_number_top + 1.0) * the_fundamental;
  7753. is_split = 1;
  7754. } else if(partial_number_foot < 0.0) {
  7755. upper_partial_number_foot = partial_number_foot + ARPEG_RANGE;
  7756. upper_partial_number_top = ARPEG_RANGE;
  7757. lower_partial_number_foot = 0.0;
  7758. lower_partial_number_top = partial_number_top;
  7759. lobandbot = (lower_partial_number_foot + 1.0) * the_fundamental;
  7760. lobandtop = (lower_partial_number_top + 1.0) * the_fundamental;
  7761. hibandbot = (upper_partial_number_foot + 1.0) * the_fundamental;
  7762. hibandtop = (upper_partial_number_top + 1.0) * the_fundamental;
  7763. is_split = 1;
  7764. } else {
  7765. lobandbot = (partial_number_foot + 1.0) * the_fundamental;
  7766. lobandtop = (partial_number_top + 1.0) * the_fundamental;
  7767. is_split = 0;
  7768. }
  7769. bwidth = ARPEG_WIN_WIDTH * the_fundamental;
  7770. do_arpegg = 1; // and setup arpeggiation flag
  7771. }
  7772. dotopfill = 0;
  7773. if(dz->vflag[RECOLOR_FIL]) { // Attempt to fill top of spectrum, where src is shrunk in spectral range
  7774. switch(dz->mode) {
  7775. case(F_OCTSHIFT): if(dz->iparam[COLINT] < 0) dotopfill = 1; break;
  7776. case(F_FRQSHIFT): // fall thro
  7777. case(F_TRANS): if(dz->param[COLINT] < 0) dotopfill = 1; break;
  7778. case(F_RESPACE): if(dz->param[COLINT] < the_fundamental) dotopfill = 1; break;
  7779. }
  7780. }
  7781. if((exit_status = get_totalamp(&pre_amptotal,dz->flbufptr[0],dz->wanted))<0)
  7782. return(exit_status);
  7783. // initialise the extra "windowbuf"
  7784. memset((char *)dz->windowbuf[0],0,dz->wanted * sizeof(float));
  7785. // Get frq-moving value
  7786. switch(dz->mode) {
  7787. case(F_OCTSHIFT): frqtrans = pow(2.0,dz->iparam[COLINT]); break;
  7788. case(F_TRANS): frqtrans = pow(2.0,dz->param[COLFLT]/SEMITONES_PER_OCTAVE); break;
  7789. case(F_FRQSHIFT): frqshift = dz->param[COLFLT]; break;
  7790. case(F_RESPACE): frqshift = dz->param[COLFLT]; break;
  7791. case(F_RAND):
  7792. randomisation = dz->param[COLFLT];
  7793. rand = (drand48() * 2.0) - 1.0; // For rand option, generate number in range -1 TO +1 or less
  7794. rand /= 2.0; // to range +- 1/2.
  7795. rand *= randomisation; // Some value with this range, or a smaller range around centre at 0.0
  7796. frqshift = the_fundamental * rand; // Step is <= +- 1/2 distance between harmonics
  7797. break;
  7798. case(F_PINVERT):
  7799. if((exit_status = pitch_invert(&newfrq,the_fundamental,dz))<0)
  7800. return exit_status;
  7801. frqtrans = newfrq/the_fundamental;
  7802. break;
  7803. case(F_PEXAGG):
  7804. if((exit_status = exag_pitchline(&newfrq,dz->pitches[inner_lpcnt],minpitch,maxpitch,dz))<0)
  7805. return exit_status;
  7806. frqtrans = newfrq/the_fundamental;
  7807. break;
  7808. case(F_PCHRAND):// fall thro
  7809. case(F_PQUANT):
  7810. newfrq = dz->pitches2[inner_lpcnt];
  7811. frqtrans = newfrq/the_fundamental;
  7812. break;
  7813. }
  7814. // Do the frq change required, on the fundamental
  7815. switch(dz->mode) {
  7816. case(F_RESPACE): newfrq = the_fundamental; break;
  7817. case(F_OCTSHIFT): // fall thro
  7818. case(F_TRANS): newfrq = (float)(the_fundamental * frqtrans); break;
  7819. case(F_FRQSHIFT): // fall thro
  7820. case(F_RAND): newfrq = (float)min(FSPEC_MINFRQ,max((float)(the_fundamental + frqshift),dz->nyquist)); break;
  7821. case(F_ARPEG): newfrq = the_fundamental; break;
  7822. }
  7823. // If EXI flag set, (non-harmonics channels TO BE zeroed)
  7824. // Find and transpose the partials: placing them in "windowbuf"
  7825. if(dz->vflag[RECOLOR_EXI]) {
  7826. 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)
  7827. return exit_status;
  7828. // Then delete the non-partial channel data
  7829. for(cc=0,vc=0;cc < dz->clength;cc++,vc+=2) {
  7830. if(dz->windowbuf[0][FREQ] <= 0.0) {
  7831. dz->windowbuf[0][AMPP] = 0.0;
  7832. dz->windowbuf[0][FREQ] = (float)((double)cc * dz->chwidth);
  7833. }
  7834. }
  7835. // Finally, copy transformed spectrum back into flbufptr, ready for output
  7836. memcpy((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],dz->wanted * sizeof(float));
  7837. } else {
  7838. // Otherwise, modify the entire spectrum:
  7839. // First appegiate the entire spectrum (i.e. run the arpeggiation window over the entire spectrum)
  7840. if(dz->mode == F_ARPEG || do_arpegg) {
  7841. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7842. thisfrq = dz->flbufptr[0][FREQ];
  7843. if((exit_status = arpeggiate(&arpegamp,thisfrq,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,is_split,dz))<0)
  7844. return exit_status;
  7845. dz->flbufptr[0][AMPP] = (float)arpegamp;
  7846. }
  7847. }
  7848. // For transposed or shifted data, put the transformed data into "windowbuf" in the appropriate (new) channel
  7849. if(dz->mode != F_ARPEG) {
  7850. switch(dz->mode) {
  7851. case(F_OCTSHIFT): // fall thro
  7852. case(F_TRANS): // fall thro
  7853. case(F_PINVERT): // fall thro
  7854. case(F_PEXAGG): // fall thro
  7855. case(F_PQUANT): // fall thro
  7856. case(F_PCHRAND): // fall thro
  7857. case(F_FRQSHIFT):
  7858. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7859. if(dz->mode == F_FRQSHIFT)
  7860. newfrq = (float)(dz->flbufptr[0][FREQ] + frqshift); // Frqshift
  7861. else // OR
  7862. newfrq = (float)(dz->flbufptr[0][FREQ] * frqtrans); // Transpose
  7863. newcc = (int)round(newfrq/dz->chwidth); // Find appropriate new channel
  7864. if(newcc >= 0 && newcc <= dz->clength-1) { // If channel is within range
  7865. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) { // IF new data is louder than any data already copied into thus location
  7866. dz->windowbuf[0][newcc*2 + 1] = newfrq; // Copy data into windowbuf
  7867. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  7868. }
  7869. }
  7870. }
  7871. break;
  7872. case(F_RESPACE):
  7873. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7874. newfrq = dz->flbufptr[0][FREQ];
  7875. if(newfrq >= the_fundamental) { // For all data above the fundamental
  7876. newfrq -= the_fundamental; // Shrink its distance above fundamental, by ratio new-harm spacing to orig
  7877. newfrq *= (float)(frqshift/the_fundamental); // and add back onto fundamental
  7878. newfrq += the_fundamental;
  7879. }
  7880. newcc = (int)round(newfrq/dz->chwidth);
  7881. if(newcc >= 0 && newcc <= dz->clength-1) {
  7882. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) {
  7883. dz->windowbuf[0][newcc*2 + 1] = (float)(newfrq);
  7884. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  7885. }
  7886. }
  7887. }
  7888. break;
  7889. case(F_RAND):
  7890. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7891. frq = dz->flbufptr[0][FREQ];
  7892. rand = (drand48() * 2.0) - 1.0;
  7893. rand /= 2.0;
  7894. rand *= randomisation;
  7895. frqshift = the_fundamental * rand;
  7896. newfrq = (float)(dz->flbufptr[0][FREQ] + frqshift);
  7897. newcc = (int)round(newfrq/dz->chwidth);
  7898. if(newcc >= 0 && newcc <= dz->clength-1) {
  7899. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) {
  7900. dz->windowbuf[0][newcc*2 + 1] = (float)(newfrq);
  7901. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  7902. }
  7903. }
  7904. }
  7905. break;
  7906. }
  7907. if(dotopfill) {
  7908. for(cc = dz->clength-1,vc=cc*2;cc >= 0;cc--,vc-=2) {
  7909. if(dz->windowbuf[0][FREQ] > 0.0) {
  7910. endamp = dz->windowbuf[0][AMPP];
  7911. break;
  7912. }
  7913. }
  7914. dotopfill = cc+1;
  7915. if((exit_status = do_top_of_spectrum_fill(dotopfill,endamp,the_fundamental,frqtrans,frqshift,&tail,dz))<0)
  7916. return exit_status;
  7917. }
  7918. // Put a reasonable freq on channels which have not received new data (HEREH : should these remain amp zero ??)
  7919. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7920. if(dz->windowbuf[0][FREQ] == 0.0)
  7921. dz->windowbuf[0][FREQ] = (float)(cc * dz->chwidth);
  7922. }
  7923. // Extract envelope of new data, into specenvamp2
  7924. if(!(dz->mode == F_PCHRAND && dz->vflag[NO_RESHAPE])) {
  7925. dz->flbufptr[1] = dz->windowbuf[0];
  7926. if((exit_status = extract_specenv(1,1,dz))<0)
  7927. return(exit_status);
  7928. // Impose the ORIGINAL spectral envelope on the new data
  7929. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7930. frq = dz->windowbuf[0][FREQ]; // At new-spectrum channel-frq
  7931. if((exit_status = getspecenvamp(&newspecamp,frq,1,dz))<0) // Get amplitude on spectral envelope of new-spectrum, at this freq
  7932. return(exit_status);
  7933. if((exit_status = getspecenvamp(&origspecamp,frq,0,dz))<0) // Get amplitude on spectral envelope of original-spectrum, at this freq
  7934. return(exit_status);
  7935. if(newspecamp <= 0.0) // Check for zeros, in either spectrum
  7936. dz->windowbuf[0][AMPP] = 0.0f;
  7937. else {
  7938. vocode_ratio = origspecamp/newspecamp;
  7939. thisamp = dz->windowbuf[0][AMPP] * vocode_ratio;
  7940. if(thisamp < VERY_TINY_VAL)
  7941. dz->windowbuf[0][AMPP] = 0.0f;
  7942. else
  7943. dz->windowbuf[0][AMPP] = (float)thisamp;
  7944. }
  7945. }
  7946. if(tail > 0) { // Any top-of-spectrum insertions, tail away to zero
  7947. for(k = 1,cc = dz->clength-1,vc = cc*2;k <= tail;k++,cc--,vc-=2) {
  7948. incr = pow((double)k/(double)(tail+1),TAILOFF_SLOPE);
  7949. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * incr);
  7950. }
  7951. }
  7952. }
  7953. // Finally, copy transformed spectrum back into flbufptr, ready for output
  7954. memcpy((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],dz->wanted * sizeof(float));
  7955. }
  7956. }
  7957. // Now advance phase of arpeggiator
  7958. *up = nextup;
  7959. *phase = nextphase;
  7960. // Do any spoecified lopass and hipass filtering
  7961. if(dz->param[COL_LO] > 0.0) {
  7962. searchfrqlimit = dz->param[COL_LO] + (dz->chwidth * 2);
  7963. for(cc=0,vc=0;cc <dz->clength;cc++,vc+=2) {
  7964. if(dz->flbufptr[0][FREQ] < dz->param[COL_LO])
  7965. dz->flbufptr[0][AMPP] = 0.0f;
  7966. else if(dz->flbufptr[0][FREQ] > searchfrqlimit)
  7967. break;
  7968. }
  7969. }
  7970. if(dz->param[COL_HI] > 0.0) {
  7971. searchfrqlimit = dz->param[COL_HI] - (dz->chwidth * 2);
  7972. for(cc=0,vc=2;cc <dz->clength;cc++,vc+=2) {
  7973. if(dz->flbufptr[0][FREQ] < searchfrqlimit)
  7974. continue;
  7975. else if(dz->flbufptr[0][FREQ] > dz->param[COL_HI])
  7976. dz->flbufptr[0][AMPP] = 0.0f;
  7977. }
  7978. }
  7979. if((exit_status = get_totalamp(&post_amptotal,dz->flbufptr[0],dz->wanted))<0)
  7980. return(exit_status);
  7981. if(post_amptotal > pre_amptotal) {
  7982. if((exit_status = normalise(pre_amptotal,post_amptotal,dz))<0)
  7983. return(exit_status);
  7984. }
  7985. // Apply any user entered attenuation
  7986. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  7987. for(vc=0;vc<dz->wanted;vc+=2)
  7988. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  7989. }
  7990. return FINISHED;
  7991. }
  7992. /************************* ARPEGGIATE *************************
  7993. *
  7994. * Arpeggaite runs a small, inverted cosin, window over the first 16 harmonics,
  7995. * recycling baclk to harmonic 1, qwhen it overruns the top of this range.
  7996. *
  7997. * 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)
  7998. *
  7999. * The window itself is ARPEG_WIN_WIDTH partials wide. | 1 |
  8000. * | _ |
  8001. * So, any partial (i.e. data in dz->windowbuf[0]) falling under this window | / \ |
  8002. * (OR any data at all, in the flbufptr, when non-harmonic data not Suppressed). | / \ -->>|
  8003. * has its amplitude multiplied by the window. | 0 / \ 0 |
  8004. * | _ / \ _ |
  8005. * | _ |
  8006. * Partial Nos 0 1 2 3 4 5 6 7
  8007. * Root multipliers 1 2 3 4 5 6 7 8
  8008. */
  8009. int arpeggiate(double *arpegamp,float frq,double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int is_split,dataptr dz)
  8010. {
  8011. double frq_offset_under_window, shaping;
  8012. if(frq > lobandbot && frq < lobandtop) {
  8013. frq_offset_under_window = (frq - lobandbot)/bwidth;
  8014. shaping = -cos(frq_offset_under_window * TWOPI); // Range -1/+1/-1
  8015. shaping = max(0.0,shaping + 1.0); // Range 0 /+2/ 0
  8016. shaping = min(1.0,shaping/2.0); // Range 0 /+1/ 0
  8017. } else if(is_split && (frq > hibandbot && frq < hibandtop)) {
  8018. frq_offset_under_window = (frq - hibandbot)/bwidth;
  8019. shaping = -cos(frq_offset_under_window * TWOPI); // Range -1/+1/-1
  8020. shaping = max(0.0,shaping + 1.0); // Range 0 /+2/ 0
  8021. shaping = min(1.0,shaping/2.0); // Range 0 /+1/ 0
  8022. } else
  8023. shaping = 0.0; // Zero partial amplitude
  8024. *arpegamp = shaping;
  8025. return FINISHED;
  8026. }
  8027. /************************************ FIND_AND_CHANGE_PARTIALS ***************************/
  8028. int find_and_change_partials(float the_fundamental,float newfrq,int *isharm,double frqshift,double frqtrans,double randomisation,
  8029. double bwidth,double lobandbot,double lobandtop,double hibandbot,double hibandtop,int do_arpegg,int is_split,dataptr dz)
  8030. {
  8031. int exit_status, cc, vc, thiscc, kcc, kvc, newcc, harmonic_found_in_src, harmonic_no;
  8032. int most_appropriate_chan, harmonicbandcnt, firstchan_with_harmonic, lastchan_with_harmonic, above_most_approp_offset, below_most_approp_offset;
  8033. float thisfrq, chancentre, thatchancentre, thatfrq, the_harmonicfrq;
  8034. double this_chan_frq_offset, that_chan_frq_offset, specamp = 0.0, arpegamp;
  8035. double rand;
  8036. the_harmonicfrq = the_fundamental;
  8037. harmonic_no = 1;
  8038. harmonic_found_in_src = 0;
  8039. // HARMONICS FOUND IN SRC IN MULTIPLE CHANNELS, Have multiple channels in output
  8040. // If a particular harmonic NOT FOUND in src, put it in a single channel in output
  8041. for(cc = 0,vc = 0;cc < dz->clength;cc++,vc+=2) {
  8042. thisfrq = dz->flbufptr[0][FREQ];
  8043. if(is_above_equivalent_pitch(thisfrq,the_harmonicfrq,dz)) { // Once the channel data is higher than the current harmonic frq, move to next harmonic
  8044. if(!harmonic_found_in_src) {
  8045. if(newfrq < dz->nyquist && newfrq > FSPEC_MINFRQ) { // BUT if no channel with current harmonic HAS BEEN found, insert it in a single channel
  8046. if(do_arpegg) {
  8047. if((exit_status = arpeggiate(&arpegamp,the_harmonicfrq,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,is_split,dz))<0)
  8048. return exit_status;
  8049. } else
  8050. arpegamp = 1.0;
  8051. thiscc = (int)floor((fabs(newfrq) + dz->halfchwidth)/dz->chwidth);
  8052. vc = thiscc*2;
  8053. dz->windowbuf[0][FREQ] = newfrq;
  8054. if((exit_status = getspecenvamp(&specamp,newfrq,0,dz))<0)
  8055. return(exit_status);
  8056. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);
  8057. }
  8058. }
  8059. the_harmonicfrq += the_fundamental; // Move to next harmonic
  8060. harmonic_no++;
  8061. if(the_harmonicfrq >= dz->nyquist)
  8062. break;
  8063. harmonic_found_in_src = 0; // Set flag telling us whether THIS harmonic is founds in src
  8064. if(dz->mode == F_RAND) {
  8065. rand = (drand48() * 2.0) - 1.0; // For rand option, generate number in range -1 TO +1 or less
  8066. rand /= 2.0; // to range +- 1/2.
  8067. rand *= randomisation; // Some value with this range, or a smaller range around centre at 0.0
  8068. frqshift = the_fundamental * rand; // Step is <= +- 1/2 distance between harmonics
  8069. }
  8070. switch(dz->mode) { // Do the frq change required
  8071. case(F_RESPACE): newfrq = (float)(the_fundamental + (frqshift * harmonic_no)); break;
  8072. case(F_OCTSHIFT): // fall thro
  8073. case(F_PINVERT): // fall thro
  8074. case(F_PEXAGG): // fall thro
  8075. case(F_PQUANT): // fall thro
  8076. case(F_PCHRAND): // fall thro
  8077. case(F_TRANS): newfrq = (float)(the_harmonicfrq * frqtrans); break;
  8078. case(F_FRQSHIFT): // fall thro
  8079. case(F_RAND): newfrq = (float)min(FSPEC_MINFRQ,max((float)(the_harmonicfrq + frqshift),dz->nyquist)); break;
  8080. case(F_ARPEG): newfrq = the_harmonicfrq; break;
  8081. }
  8082. if(newfrq >= dz->nyquist || newfrq < FSPEC_MINFRQ) // If shifted frq becomes out of range, quit
  8083. break;
  8084. }
  8085. if(is_equivalent_pitch(thisfrq,the_harmonicfrq,dz)) { // IF freq in channel a harmonic
  8086. if(do_arpegg) {
  8087. if((exit_status = arpeggiate(&arpegamp,the_harmonicfrq,bwidth,lobandbot,lobandtop,hibandbot,hibandtop,is_split,dz))<0)
  8088. return exit_status;
  8089. } else
  8090. arpegamp = 1.0;
  8091. isharm[cc] = 1;
  8092. harmonic_found_in_src = 1;
  8093. chancentre = (float)(cc * dz->chwidth); // Look in channels immediately above this
  8094. this_chan_frq_offset = fabs(thisfrq - chancentre);
  8095. most_appropriate_chan = cc;
  8096. harmonicbandcnt = 1;
  8097. firstchan_with_harmonic = cc;
  8098. lastchan_with_harmonic = cc;
  8099. kcc = cc + 1; // How many adjacent channels contain this harmonic
  8100. for(kvc = kcc*2;kcc < dz->clength;kcc++,kvc+=2) {
  8101. thatchancentre = (float)(kcc * dz->chwidth); // And which channel-centre is closest to the harmonic-frq
  8102. thatfrq = dz->flbufptr[0][kvc+1];
  8103. if(is_equivalent_pitch(thatfrq,the_harmonicfrq,dz)) {
  8104. isharm[kcc] = 1;
  8105. harmonicbandcnt++;
  8106. that_chan_frq_offset = fabs(thatfrq - thatchancentre);
  8107. if(that_chan_frq_offset < this_chan_frq_offset) {
  8108. most_appropriate_chan = kcc;
  8109. this_chan_frq_offset = that_chan_frq_offset;
  8110. }
  8111. }
  8112. else // If no futher adjacent channels containing this harmonic are found
  8113. break; // break from search for further chans containing the harmonic.
  8114. }
  8115. // Put the transposed harmonic into the appropriate new channel
  8116. newcc = (int)floor((fabs(newfrq) + dz->halfchwidth)/dz->chwidth);
  8117. vc = newcc*2;
  8118. dz->windowbuf[0][FREQ] = newfrq; // windowbuf stores the transposed-harmonics data
  8119. if((exit_status = getspecenvamp(&specamp,newfrq,0,dz))<0) // but under the original formant envelope
  8120. return(exit_status);
  8121. if(harmonicbandcnt > 1) // If harmonic appeared in > 1 adjacent channels
  8122. specamp /= (double)harmonicbandcnt; // Divide amp between chans that share this frequency
  8123. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);
  8124. if(harmonicbandcnt > 1) { // If harmonic appeared in > 1 adjacent channels
  8125. lastchan_with_harmonic = kcc-1;
  8126. above_most_approp_offset = lastchan_with_harmonic - most_appropriate_chan;
  8127. below_most_approp_offset = most_appropriate_chan - firstchan_with_harmonic;
  8128. if(below_most_approp_offset > 0) { // Fill same number of adjacent channels at new location
  8129. thiscc = max(newcc - below_most_approp_offset,0);
  8130. for(vc = thiscc*2;thiscc < newcc;thiscc++,vc+=2) {
  8131. dz->windowbuf[0][FREQ] = newfrq;
  8132. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);;
  8133. }
  8134. }
  8135. if(above_most_approp_offset > 0) {
  8136. thiscc = min(newcc + above_most_approp_offset,dz->clength - 1);
  8137. for(vc = thiscc*2;thiscc > newcc;thiscc--,vc-=2) {
  8138. dz->windowbuf[0][FREQ] = newfrq;
  8139. dz->windowbuf[0][AMPP] = (float)(specamp * arpegamp);
  8140. }
  8141. }
  8142. }
  8143. cc = lastchan_with_harmonic; // Move search to last appearance of this harmonic
  8144. vc = cc * 2;
  8145. the_harmonicfrq += the_fundamental; // And go to next harmonic
  8146. harmonic_no++;
  8147. if(the_harmonicfrq >= dz->nyquist)
  8148. break;
  8149. if(dz->mode ==F_RAND) { // Generating the next transformed frq
  8150. rand = (drand48() * 2.0) - 1.0;
  8151. rand /= 2.0;
  8152. rand *= randomisation;
  8153. frqshift = the_fundamental * rand;
  8154. }
  8155. switch(dz->mode) {
  8156. case(F_RESPACE): newfrq = (float)(the_fundamental + (frqshift * harmonic_no)); break;
  8157. case(F_OCTSHIFT): // fall thro
  8158. case(F_PINVERT): // fall thro
  8159. case(F_PEXAGG): // fall thro
  8160. case(F_PQUANT): // fall thro
  8161. case(F_PCHRAND): // fall thro
  8162. case(F_TRANS): newfrq = (float)(the_harmonicfrq * frqtrans); break;
  8163. case(F_FRQSHIFT): // fall thro
  8164. case(F_RAND): newfrq = (float)(the_harmonicfrq + frqshift); break;
  8165. case(F_ARPEG): newfrq = the_harmonicfrq; break;
  8166. }
  8167. if(newfrq >= dz->nyquist || newfrq < FSPEC_MINFRQ) // If shifted frq becomes out of range, quit
  8168. break;
  8169. }
  8170. }
  8171. return FINISHED;
  8172. }
  8173. /************************************ IS_COLORING ***************************/
  8174. int is_coloring(dataptr dz)
  8175. {
  8176. switch(dz->mode) {
  8177. case(F_OCTSHIFT): // fall thro
  8178. case(F_TRANS): // fall thro
  8179. case(F_FRQSHIFT): // fall thro
  8180. case(F_RESPACE): // fall thro
  8181. case(F_PINVERT): // fall thro
  8182. case(F_PEXAGG): // fall thro
  8183. case(F_PQUANT): // fall thro
  8184. case(F_PCHRAND): // fall thro
  8185. case(F_RAND): return TRUE; break;
  8186. }
  8187. return FALSE;
  8188. }
  8189. /************************************ DO_TOP_OF_SPECTRUM_FILL ***************************/
  8190. int do_top_of_spectrum_fill(int cc,float endamp,float the_fundamental,double frqtrans,double frqshift,int *tail,dataptr dz)
  8191. {
  8192. int finished = 0, newcc, lastnewcc = -1;
  8193. float newfrq;
  8194. double frq;
  8195. frq = dz->nyquist;
  8196. while (!finished) {
  8197. frq += dz->chwidth;
  8198. switch(dz->mode) {
  8199. case(F_OCTSHIFT): // fall thro
  8200. case(F_TRANS): // fall thro
  8201. case(F_FRQSHIFT):
  8202. if(dz->mode == F_FRQSHIFT)
  8203. newfrq = (float)(frq + frqshift);
  8204. else
  8205. newfrq = (float)(frq * frqtrans);
  8206. newcc = (int)round(newfrq/dz->chwidth);
  8207. if(newcc >= 0 && newcc <= dz->clength-1) {
  8208. dz->windowbuf[0][newcc*2 + 1] = newfrq;
  8209. dz->windowbuf[0][newcc*2] = endamp;
  8210. if(newcc > lastnewcc)
  8211. (*tail)++;
  8212. lastnewcc = newcc;
  8213. } else
  8214. finished = 1;
  8215. break;
  8216. case(F_RESPACE):
  8217. newfrq = (float)frq;
  8218. if(newfrq >= the_fundamental) {
  8219. newfrq -= the_fundamental;
  8220. newfrq *= (float)(frqshift/the_fundamental);
  8221. newfrq += the_fundamental;
  8222. }
  8223. newcc = (int)round(newfrq/dz->chwidth);
  8224. if(newcc >= 0 && newcc <= dz->clength-1) {
  8225. dz->windowbuf[0][newcc*2 + 1] = (float)(newfrq);
  8226. dz->windowbuf[0][newcc*2] = endamp;
  8227. if(newcc > lastnewcc)
  8228. (*tail)++;
  8229. lastnewcc = newcc;
  8230. } else
  8231. finished = 1;
  8232. break;
  8233. }
  8234. }
  8235. return FINISHED;
  8236. }
  8237. /************************************ GETMEANPITCH ***************************/
  8238. int getmeanpitch(double *meanpitch,double *minpitch,double *maxpitch,dataptr dz)
  8239. {
  8240. int n, sumcnt = 0;
  8241. double maxpitchfrq = -HUGE, minpitchfrq = HUGE;
  8242. *meanpitch = 0.0;
  8243. for(n = 0; n < dz->wlength; n++) {
  8244. if(dz->pitches[n] >= MINPITCH) {
  8245. maxpitchfrq = max(maxpitchfrq,dz->pitches[n]);
  8246. minpitchfrq = min(minpitchfrq,dz->pitches[n]);
  8247. *meanpitch += unchecked_hztomidi(dz->pitches[n]);
  8248. sumcnt++;
  8249. }
  8250. }
  8251. *meanpitch /= (double)sumcnt;
  8252. *minpitch = unchecked_hztomidi(minpitchfrq);
  8253. *maxpitch = unchecked_hztomidi(maxpitchfrq);
  8254. if(*maxpitch < 0.0) {
  8255. sprintf(errstr,"Failed to find maximum pitch in pitch data: (Possibly no definite pitch in file?)\n");
  8256. return GOAL_FAILED;
  8257. }
  8258. if(*minpitch > 200) {
  8259. sprintf(errstr,"Failed to find minimum pitch in pitch data: (Possibly no definite pitch in file?)\n");
  8260. return GOAL_FAILED;
  8261. }
  8262. return FINISHED;
  8263. }
  8264. /************************** INTERVAL_MAPPING ************************
  8265. *
  8266. * Approximate input interval to nearest value in LHS column of input map.
  8267. * Find variance from that value.
  8268. * Return corresponding value in RHS column of map, with the variance correction added.
  8269. */
  8270. int interval_mapping(double *thisint,double thismidi,dataptr dz)
  8271. {
  8272. double *p = dz->parray[F_PINTMAP], *q;
  8273. double *pend = dz->parray[F_PINTMAP] + (dz->itemcnt * 2);
  8274. double variance, v1, v2;
  8275. // Normally, points to the normal upeard interval
  8276. q = p+1; // and q points to the correspoinding downward interval
  8277. if(*p < 0.0) { // But interval is already downward (-ve)
  8278. p = q; // we read the inverted intervals column
  8279. q = p-1; // and map to the non-inverted
  8280. }
  8281. if(thismidi <= *p) { /* intvl is below all entries in mapping table */
  8282. variance = thismidi - *p;
  8283. *thisint = *q - variance; /* return map of bottom val (-variance) */
  8284. return(FINISHED);
  8285. }
  8286. while(thismidi > *p) {
  8287. p += 2;
  8288. q += 2;
  8289. if(p >= pend) { /* intvl is above all entries in mapping table */
  8290. p -= 2;
  8291. q -= 2;
  8292. variance = thismidi - *p;
  8293. *thisint = *q - variance; /* return map of top val (-variance) */
  8294. return(FINISHED);
  8295. }
  8296. }
  8297. v1 = *p - thismidi; /* intvl is between 2 entries in mapping table */
  8298. v2 = thismidi - *(p-2);
  8299. if(v1 > v2) { /* Compare variances, to find which intvl closer */
  8300. variance = v2;
  8301. *thisint = *(q-2) - variance;
  8302. } else {
  8303. variance = v1;
  8304. *thisint = *q + variance; /* return appropriate mapped pitch (+/-variance) */
  8305. }
  8306. return(FINISHED);
  8307. }
  8308. /********************** READ_INTERVAL_MAPPING ************************/
  8309. int read_interval_mapping(char *filename,dataptr dz)
  8310. {
  8311. int exit_status;
  8312. double *p;
  8313. int n, m;
  8314. double src_n, src_m, goal_n, goal_m;
  8315. if(!strcmp(filename,"0"))
  8316. dz->is_mapping = FALSE;
  8317. else {
  8318. // Get data from textfile
  8319. if((exit_status = get_and_count_data_from_textfile(filename,&(dz->parray[F_PINTMAP]),dz))<0)
  8320. return(exit_status);
  8321. p = dz->parray[F_PINTMAP];
  8322. // Check range of data
  8323. for(n=0;n<dz->itemcnt;n++) {
  8324. if(*p < -MAXINTRANGE || *p > MAXINTRANGE) {
  8325. sprintf(errstr,
  8326. "Mapping val (%lf) out of range (%.0lf to -%.0lf semitones) (8 8vas up or down).\n",
  8327. *p,MAXINTRANGE,MAXINTRANGE);
  8328. return(DATA_ERROR);
  8329. }
  8330. p++;
  8331. }
  8332. if(ODD(dz->itemcnt)) {
  8333. sprintf(errstr,"Data not paired correctly in mapping file\n");
  8334. return(DATA_ERROR);
  8335. }
  8336. // Sort mapping data
  8337. for(n=0;n<dz->itemcnt-2;n+=2) {
  8338. src_n = dz->parray[F_PINTMAP][n];
  8339. goal_n = dz->parray[F_PINTMAP][n+1];
  8340. for(m = n+2;m<dz->itemcnt;m+=2) {
  8341. src_m = dz->parray[F_PINTMAP][m];
  8342. goal_m = dz->parray[F_PINTMAP][m+1];
  8343. if(src_n > src_m) {
  8344. dz->parray[F_PINTMAP][n] = src_m;
  8345. dz->parray[F_PINTMAP][m] = src_n;
  8346. dz->parray[F_PINTMAP][n+1] = goal_m;
  8347. dz->parray[F_PINTMAP][m+1] = goal_n;
  8348. src_n = src_m;
  8349. goal_n = goal_m;
  8350. }
  8351. }
  8352. }
  8353. dz->itemcnt /= 2;
  8354. dz->is_mapping = TRUE;
  8355. }
  8356. return(FINISHED);
  8357. }
  8358. /*************************** GET_AND_COUNT_DATA_FROM_TEXTFILE ******************************
  8359. *
  8360. * (1) Gets double table data from a text file.
  8361. * (2) counts ALL items (not pairing them).
  8362. * (3) Does NOT check for in-range.
  8363. */
  8364. int get_and_count_data_from_textfile(char *filename,double **brktable,dataptr dz)
  8365. {
  8366. FILE *fp;
  8367. double *p, dummy;
  8368. char temp[200], *q;
  8369. int n = 0;
  8370. if((fp = fopen(filename,"r"))==NULL) {
  8371. sprintf(errstr, "Can't open textfile %s to read data.\n",filename);
  8372. return(DATA_ERROR);
  8373. }
  8374. n = 0;
  8375. while(fgets(temp,200,fp)==temp) {
  8376. q = temp;
  8377. if(*q == ';') // Allow comments in file
  8378. continue;
  8379. while(get_float_from_within_string(&q,&dummy))
  8380. n++;
  8381. }
  8382. if(n == 0) {
  8383. sprintf(errstr,"No data in special data file %s\n",filename);
  8384. return(DATA_ERROR);
  8385. }
  8386. if((*brktable = (double *)malloc(n * sizeof(double)))==NULL) {
  8387. sprintf(errstr,"INSUFFICIENT MEMORY for data.\n");
  8388. return(MEMORY_ERROR);
  8389. }
  8390. p = *brktable;
  8391. rewind(fp);
  8392. while(fgets(temp,200,fp)==temp) {
  8393. q = temp;
  8394. if(*q == ';') // Allow comments in file
  8395. continue;
  8396. while(get_float_from_within_string(&q,p))
  8397. p++;
  8398. }
  8399. if(fclose(fp)<0) {
  8400. fprintf(stdout,"WARNING: Failed to close input textfile %s.\n",filename);
  8401. fflush(stdout);
  8402. }
  8403. dz->itemcnt = n;
  8404. return(FINISHED);
  8405. }
  8406. /************************************* EXAG_PITCHLINE ******************************/
  8407. int exag_pitchline(float *newfrq,float thisfrq,double minpich,double maxpich,dataptr dz)
  8408. {
  8409. int exit_status;
  8410. double meanpich, thisint, thispich;
  8411. dz->time = 0.0f;
  8412. meanpich = dz->param[COLFLT];
  8413. if((exit_status = hztomidi(&thispich,thisfrq))<0)
  8414. return(exit_status);
  8415. if(maxpich - meanpich > SEMITONES_PER_OCTAVE)
  8416. maxpich = meanpich + SEMITONES_PER_OCTAVE;
  8417. if(meanpich - minpich > SEMITONES_PER_OCTAVE)
  8418. minpich = meanpich - SEMITONES_PER_OCTAVE;
  8419. /* if contour variable specified */
  8420. if(dz->vflag[EXAG_HITIE]) { // TIES TO TOP OF RANGE
  8421. if(thispich > meanpich)
  8422. thispich = (float)maxpich;
  8423. else if(dz->vflag[EXAG_MIDTIE] && !dz->vflag[EXAG_LOTIE])
  8424. thispich = (float)meanpich;
  8425. }
  8426. if(dz->vflag[EXAG_LOTIE]) {
  8427. if(thispich < meanpich)
  8428. thispich = (float)minpich;
  8429. else if(dz->vflag[EXAG_MIDTIE] && !dz->vflag[EXAG_HITIE])
  8430. thispich = (float)meanpich;
  8431. }
  8432. /* If range variable specified */
  8433. if(dz->param[EXAGRANG] > 0.0) { // -1 flags no range variation
  8434. if(thispich>=meanpich) {
  8435. if(!dz->vflag[ONLY_BELOW]) {
  8436. thisint = thispich - meanpich; // What is interval from mean to this pitch
  8437. thispich = meanpich + (thisint * dz->param[EXAGRANG]);
  8438. }
  8439. } else { // Exaggerate it
  8440. if(!dz->vflag[ONLY_ABOVE]) {
  8441. thisint = meanpich - thispich; // and add-to/subtract-from mean
  8442. thispich = meanpich - (thisint * dz->param[EXAGRANG]);
  8443. }
  8444. }
  8445. } // Force pitch to be within range
  8446. thispich = min(dz->param[COLHIPCH],max(dz->param[COLLOPCH],thispich));
  8447. *newfrq = (float)miditohz(thispich);
  8448. return(FINISHED);
  8449. }
  8450. /************************************* PITCH_INVERT ******************************/
  8451. int pitch_invert(float *newfrq,float the_fundamental,dataptr dz)
  8452. {
  8453. int exit_status;
  8454. double pivotpitch, rootpitch, newpitch, thisintvl, newintvl;
  8455. pivotpitch = dz->param[COLINT];
  8456. rootpitch = unchecked_hztomidi(the_fundamental);
  8457. thisintvl = pivotpitch - rootpitch;
  8458. if(dz->is_mapping) {
  8459. if((exit_status = interval_mapping(&newintvl,thisintvl,dz))<0)
  8460. return(exit_status);
  8461. thisintvl = newintvl;
  8462. }
  8463. newpitch = max(dz->param[COLLOPCH],min(dz->param[COLHIPCH],pivotpitch + thisintvl));
  8464. *newfrq = (float)miditohz(newpitch);
  8465. return FINISHED;
  8466. }
  8467. /********************************** PITCH_QUANTISE_ALL **************************/
  8468. int pitch_quantise_all(dataptr dz)
  8469. {
  8470. int exit_status, at_timehfend = 0;
  8471. double *pstt, *pend, *abs_pend = NULL, *next_pstt = NULL, *next_pend = NULL;
  8472. double thismidi, qmidi, qmidi1, qmidi2, thistime = 0.0, nexttime = 0.0, time, time_ratio = 1.0;
  8473. int n;
  8474. pstt = dz->parray[QUANTPITCH];
  8475. if(dz->timedhf) {
  8476. abs_pend = pstt + (dz->quantcnt * dz->itemcnt) - 1;
  8477. thistime = 0.0;
  8478. pend = pstt + dz->quantcnt - 1;
  8479. if(pend >= abs_pend)
  8480. at_timehfend = 1;
  8481. else {
  8482. next_pstt = pstt + dz->quantcnt;
  8483. next_pend = next_pstt + dz->quantcnt - 1;
  8484. nexttime = *next_pstt;
  8485. }
  8486. } else
  8487. pend = pstt + dz->quantcnt - 1;
  8488. for(n=0;n<dz->wlength;n++) {
  8489. if(dz->pitches[n] < MINPITCH) {
  8490. dz->pitches2[n] = dz->pitches[n];
  8491. continue;
  8492. }
  8493. if(dz->timedhf && !at_timehfend){
  8494. time = dz->frametime * n;
  8495. if(time > nexttime) {
  8496. if(next_pstt + dz->quantcnt >= abs_pend) {
  8497. at_timehfend = 1;
  8498. pstt++; // Change to the normal convention, MIDI data starts AFTER the time value
  8499. } else {
  8500. thistime = nexttime;
  8501. pstt = next_pstt;
  8502. pend = next_pend;
  8503. next_pstt += dz->quantcnt;
  8504. next_pend += dz->quantcnt;
  8505. nexttime = *next_pstt;
  8506. }
  8507. }
  8508. if(!at_timehfend)
  8509. time_ratio = (time - thistime)/(nexttime - thistime);
  8510. }
  8511. if((exit_status = hztomidi(&thismidi,dz->pitches[n]))<0)
  8512. return(exit_status);
  8513. if(dz->timedhf && !at_timehfend) {
  8514. qmidi1 = pitch_quantise(thismidi,pstt+1,pend,dz); // pstt is a time val: Timevarying HF MIDI vals start at pstt+1
  8515. qmidi2 = pitch_quantise(thismidi,next_pstt+1,next_pend,dz);
  8516. qmidi = ((qmidi2 - qmidi1) * time_ratio) + qmidi1;
  8517. } else
  8518. qmidi = pitch_quantise(thismidi,pstt,pend,dz);
  8519. dz->pitches2[n] = (float)miditohz(qmidi);
  8520. }
  8521. // NOW SMOOTH THE DATA
  8522. return pitch_smooth(dz);
  8523. }
  8524. /********************************** PITCH_QUANTISE **************************/
  8525. double pitch_quantise(double thismidi,double *pstt, double *pend,dataptr dz)
  8526. {
  8527. double *p, qmidi;
  8528. if(thismidi <= *pstt)
  8529. qmidi = *pstt;
  8530. else if(thismidi >= *pend)
  8531. qmidi = *pend;
  8532. else {
  8533. p = pstt;
  8534. while(thismidi > *p)
  8535. p++;
  8536. if((*p - thismidi) > (thismidi - *(p-1)))
  8537. qmidi = *(p-1);
  8538. else
  8539. qmidi = *p;
  8540. }
  8541. return qmidi;
  8542. }
  8543. /********************************** PITCH_SMOOTH **************************/
  8544. int pitch_smooth(dataptr dz)
  8545. {
  8546. int exit_status, min_wcnt;
  8547. // float previouspitch;
  8548. // previouspitch = -1;
  8549. if(dz->vflag[Q_ORNAMENTS])
  8550. min_wcnt = (int)round(ORNAMENT_DUR/dz->frametime);
  8551. else
  8552. min_wcnt = (int)round(STABLE_DUR/dz->frametime);
  8553. // Pass 1: remove too-brief pitches
  8554. if((exit_status = pitchline_smooth(dz->pitches2,min_wcnt,0,dz))<0)
  8555. return exit_status;
  8556. if(dz->vflag[Q_NOSMOOTH])
  8557. return FINISHED;
  8558. // Pass 2: put in note-transitions
  8559. return smooth_note_to_note_transitions(dz->pitches2,dz);
  8560. }
  8561. /********************************** PITCH_RANDOMISE_ALL **************************
  8562. *
  8563. * Randomisation takes place over time-slots, themselves generated at randon.
  8564. * Time slots are based on a minimum time-slot, and range up to a max of PRAND_TRANGE * the min.
  8565. * To ensure we do not get a bias towards the longer slots, we take the sqrt of any value we get gtom drand48()
  8566. *
  8567. * tslot = (int)round(sqrt(drand48()) * PRAND_TRANGE) * min_wcnt);
  8568. */
  8569. int pitch_randomise_all(dataptr dz)
  8570. {
  8571. int exit_status, min_wcnt, tslot, blokcnt;
  8572. double *pstt, *pend, prand_range;
  8573. float thispitch, nextpitch;
  8574. int n, m, newwcnt;
  8575. if(dz->vflag[Q_ORNAMENTS])
  8576. min_wcnt = (int)floor(PRAND_ORN_TSTEP/dz->frametime);
  8577. else
  8578. min_wcnt = (int)floor(PRAND_TSTEP/dz->frametime);
  8579. if(dz->quantcnt) {
  8580. pstt = dz->parray[QUANTPITCH];
  8581. pend = dz->parray[QUANTPITCH] + dz->quantcnt - 1;
  8582. blokcnt = 0;
  8583. for(n=0;n<dz->wlength;n++) { // For all previously quantised pitches
  8584. thispitch = dz->pitches2[n]; // Get the startpitch of a blok having a fixed-quantised pitch
  8585. m = n;
  8586. do {
  8587. blokcnt++;
  8588. if(++m >= dz->wlength)
  8589. break;
  8590. nextpitch = dz->pitches2[m]; // count the bloksize
  8591. } while(nextpitch == thispitch);
  8592. if(blokcnt > min_wcnt) { // If the block of pitch is longer than the minimum bloksize
  8593. newwcnt = 0;
  8594. while(newwcnt < blokcnt) { // Generate rand time-slots within the blok
  8595. prand_range = (double)(blokcnt - newwcnt)/(double)min_wcnt; // Set range for random-generation between min and remaining bloksize
  8596. tslot = ((int)round(sqrt(drand48()) * prand_range) * min_wcnt) + min_wcnt;
  8597. if(newwcnt + tslot > blokcnt - min_wcnt) // If the time-slot does not leave enough space for a a futher slot, within the blok
  8598. tslot = blokcnt - newwcnt; // Forece the time-slot to take up all the remainder of the blok
  8599. // Random-generate a new pitch, and quantise it to the quantisation grid
  8600. if((exit_status = quantise_randomise_pitchblok(n,tslot,pstt,pend,dz))<0)
  8601. return exit_status;
  8602. // Set the range for random-generation between min and this bloksize
  8603. newwcnt += tslot; // Keep a running sum of window used within the pitchblok
  8604. }
  8605. } else if((exit_status = quantise_randomise_pitchblok(n,blokcnt,pstt,pend,dz))<0)
  8606. return exit_status;
  8607. blokcnt = 0;
  8608. n = m - 1; // Advance the outer loop to where inner loop has got to
  8609. }
  8610. } else {
  8611. newwcnt = 0; // For all pitches
  8612. for(n=0;n<dz->wlength;n++) {
  8613. if((exit_status = randomise_pitchblok(n,min_wcnt,&newwcnt,dz))<0)
  8614. return exit_status; // Rand-transposes a block of data in a random-sized timeslot
  8615. n = newwcnt - 1; // Outer loop jumps over transformed windows
  8616. }
  8617. }
  8618. return FINISHED;
  8619. }
  8620. /********************************** RANDOMISE_PITCHBLOK **************************/
  8621. int randomise_pitchblok(int start_win,int min_wcnt,int *newwcnt,dataptr dz)
  8622. {
  8623. int exit_status, tslot;
  8624. double thisintv;
  8625. int k, m;
  8626. tslot = ((int)round(sqrt(drand48()) * PRAND_TRANGE) * min_wcnt) + min_wcnt;
  8627. if(*newwcnt + tslot > dz->wlength - min_wcnt) // If it reaches too close to the end of the pitch data
  8628. tslot = dz->wlength - *newwcnt; // extend slot to end of pitch data.
  8629. if((exit_status = get_rand_interval(&thisintv,dz)) < 0)
  8630. return exit_status; // Add a random interval to all pitches in this slot
  8631. for(k = 0,m = start_win; k < tslot;k++,m++)
  8632. dz->pitches2[m] = (float)(dz->pitches[m] + thisintv);
  8633. *newwcnt += tslot; // Advance the cnt of transformed windows
  8634. return FINISHED;
  8635. }
  8636. /********************************** QUANTISE_RANDOMISE_PITCHBLOK **************************/
  8637. int quantise_randomise_pitchblok(int n,int wcnt,double *pstt,double *pend,dataptr dz)
  8638. {
  8639. int exit_status;
  8640. double thisintv, thispitch;
  8641. int k;
  8642. if((exit_status = get_rand_interval(&thisintv,dz)) < 0) // Generate random interval
  8643. return exit_status;
  8644. thispitch = dz->pitches2[n]; // Add interval to current pitchblok pitch
  8645. thispitch += thisintv;
  8646. thispitch = pitch_quantise(thispitch,pstt,pend,dz); // Quantise the resulting pitch
  8647. for(k=0;k <wcnt;k++) // Refill the pitchblock with the new pitch
  8648. dz->pitches2[n++] = (float)thispitch;
  8649. return FINISHED;
  8650. }
  8651. /************************** GET_RAND_INTERVAL ************************/
  8652. int get_rand_interval(double *thisintv,dataptr dz)
  8653. {
  8654. double wiggle2, wiggle = (((drand48()) * 2.0) - 1.0); // Range -1 to 1; Then fabsRange 0 - 1 warped, biasing values to top
  8655. wiggle2 = pow(fabs(wiggle),0.33); // - -
  8656. if(wiggle < 0.0) // - -
  8657. wiggle = -wiggle2; // - ->> -
  8658. else // - -
  8659. wiggle = wiggle2; // - -
  8660. // - -
  8661. *thisintv = dz->param[FPRMAXINT] * wiggle;
  8662. if(wiggle > 0.0) { // If varies upwards
  8663. if(dz->param[FSLEW] < 1.0) // If slew is (say) 0.5, upper range is 1/2 of lower range, so multiply by slew
  8664. *thisintv *= dz->param[FSLEW];
  8665. } else if(wiggle < 0.0) { // If varies downwards
  8666. if(dz->param[FSLEW] > 1.0) // If slew is (say) 2, lower range is 1/2 of upper range, so divide by slew
  8667. *thisintv /= dz->param[FSLEW];
  8668. }
  8669. return(FINISHED);
  8670. }
  8671. /************************** FORMANTS_SMOOTH_AND_QUANTISE_ALL ************************/
  8672. int formants_smooth_and_quantise_all(dataptr dz)
  8673. {
  8674. int exit_status, fno, offset, qdep_param, min_wcnt, at_timehfend = 0;
  8675. int n;
  8676. double thismidi, qmidi, qmidi1, qmidi2, quantintvl, time, thistime = 0, nexttime = 0.0, time_ratio = 1.0;
  8677. double *pstt = NULL, *pend = NULL, *next_pstt = NULL, *next_pend = NULL, *abs_pend = NULL;
  8678. float *ffrq[5], *qfrq[5];
  8679. min_wcnt = (int)floor(PRAND_TSTEP/dz->frametime); // Min number of windows to indicate a stable pitch
  8680. ffrq[1] = dz->fptr[FOR_FRQ1];
  8681. ffrq[2] = dz->fptr[FOR_FRQ2]; // Point to appropriate arrays storing formant frq-data
  8682. ffrq[3] = dz->fptr[FOR_FRQ3];
  8683. ffrq[4] = dz->fptr[FOR_FRQ4];
  8684. qfrq[1] = dz->fptr[QOR_FRQ1];
  8685. qfrq[2] = dz->fptr[QOR_FRQ2]; // Point to appropriate arrays storing eventual transposition of formant
  8686. qfrq[3] = dz->fptr[QOR_FRQ3];
  8687. qfrq[4] = dz->fptr[QOR_FRQ4];
  8688. // Array numbering error-check
  8689. n = 0;
  8690. offset = 6;
  8691. for(fno = 1;fno <= 4;fno++) {
  8692. qdep_param = fno+offset;
  8693. switch(fno) {
  8694. case(1): if(qdep_param != F_QDEP1) n = 1; break;
  8695. case(2): if(qdep_param != F_QDEP2) n = 1; break;
  8696. case(3): if(qdep_param != F_QDEP3) n = 1; break;
  8697. case(4): if(qdep_param != F_QDEP4) n = 1; break;
  8698. }
  8699. if(n) {
  8700. fprintf(stdout,"ERROR: Array numbering mismatch: formants_smooth_and_quantise_all() Change offset, or array numbers.\n");
  8701. return PROGRAM_ERROR;
  8702. }
  8703. }
  8704. if(dz->quantcnt) {
  8705. pstt = dz->parray[QUANTPITCH];
  8706. pend = pstt + dz->quantcnt - 1; // Initialise (for changing or unchanging) Quantisation Data
  8707. if(dz->timedhf) // Initialise end address of Time-changing Quantisation Data
  8708. abs_pend = pstt + (dz->quantcnt * dz->itemcnt) - 1;
  8709. }
  8710. fprintf(stdout,"INFO: Modifying formant paths.\n");
  8711. // For every formant-frq trace
  8712. for(fno = 1; fno <= 4; fno++) {
  8713. if(dz->timedhf) {
  8714. at_timehfend = 0;
  8715. pstt = dz->parray[QUANTPITCH];
  8716. thistime = 0.0;
  8717. pend = pstt + dz->quantcnt - 1;
  8718. if(pend >= abs_pend)
  8719. at_timehfend = 1;
  8720. else {
  8721. next_pstt = pstt + dz->quantcnt;
  8722. next_pend = next_pstt + dz->quantcnt - 1;
  8723. nexttime = *next_pstt;
  8724. }
  8725. }
  8726. // If data is to be quantised or smoothed
  8727. if(dz->quantcnt || dz->vflag[F_SMOOTH]) {
  8728. // First convert frq to MIDI
  8729. for(n=0;n < dz->wlength; n++) {
  8730. qdep_param = fno+offset;
  8731. if(dz->brksize[qdep_param]) {
  8732. time = dz->frametime * n;
  8733. if((exit_status = read_value_from_brktable(time,qdep_param,dz))<0)
  8734. return exit_status;
  8735. }
  8736. if(dz->timedhf && !at_timehfend){
  8737. time = dz->frametime * n;
  8738. if(time > nexttime) {
  8739. if(next_pstt + dz->quantcnt >= abs_pend) {
  8740. at_timehfend = 1; // At last data set of gtime-changing data.
  8741. pstt++; // Change to standard read convention, ignoring time-value
  8742. } else {
  8743. thistime = nexttime;
  8744. pstt = next_pstt;
  8745. pend = next_pend;
  8746. next_pstt += dz->quantcnt;
  8747. next_pend += dz->quantcnt;
  8748. nexttime = *next_pstt;
  8749. }
  8750. }
  8751. if(!at_timehfend)
  8752. time_ratio = (time - thistime)/(nexttime - thistime);
  8753. }
  8754. if(dz->pitches[n] < MINPITCH || ffrq[fno][n] < MINPITCH) { // pitch has been smoothed since extracting formants
  8755. qfrq[fno][n] = -1.0; // So no processing of formant-pitch, flagged at zero
  8756. continue; // so pitch window may now have been assigned a pitched but have no formant data
  8757. }
  8758. if((exit_status = hztomidi(&thismidi,ffrq[fno][n]))<0)
  8759. return(exit_status);
  8760. // If data is to be quantised, quantise it
  8761. if(dz->quantcnt && dz->param[qdep_param] > 0.0) {
  8762. if(dz->timedhf && !at_timehfend) {
  8763. qmidi1 = pitch_quantise(thismidi,pstt+1,pend,dz); // pstt is a time val: MIDI vals start at pstt+1
  8764. qmidi2 = pitch_quantise(thismidi,next_pstt+1,next_pend,dz);
  8765. qmidi = ((qmidi2 - qmidi1) * time_ratio) + qmidi1;
  8766. } else
  8767. qmidi = pitch_quantise(thismidi,pstt,pend,dz);
  8768. // and allow for quantisation depth parameter
  8769. if(dz->param[qdep_param] < 1.0) {
  8770. quantintvl = qmidi - thismidi;
  8771. quantintvl *= dz->param[qdep_param];
  8772. qmidi = thismidi + quantintvl;
  8773. }
  8774. thismidi = qmidi;
  8775. }
  8776. // and store (possibly transformed) MIDI vals in qfrq
  8777. qfrq[fno][n] = (float)thismidi;
  8778. }
  8779. // If data is to be smoothed, now smooth it
  8780. if(dz->vflag[F_SMOOTH]) {
  8781. if((exit_status = pitchline_smooth(qfrq[fno],min_wcnt,1,dz))<0)
  8782. return exit_status;
  8783. }
  8784. // Finally convert back to frq, then replace by frq-transposition value
  8785. for(n=0;n < dz->wlength; n++) {
  8786. if(qfrq[fno][n] < 0.0) // Zero pitch or zero-pitched formant
  8787. qfrq[fno][n] = 1.0f; // No transposition
  8788. else {
  8789. qfrq[fno][n] = (float)miditohz(qfrq[fno][n]); // Converted MIDI to frq
  8790. qfrq[fno][n] = qfrq[fno][n]/ffrq[fno][n]; // Convert frq to frq-transposition value
  8791. }
  8792. }
  8793. } else {
  8794. for(n=0;n < dz->wlength; n++)
  8795. qfrq[fno][n] = 1.0; // If no processing of formant-pitch, transposition value = 1.0
  8796. }
  8797. }
  8798. return FINISHED;
  8799. }
  8800. /************************** FORMANTS_SINUS ************************/
  8801. int formants_sinus(int inner_lpcnt,dataptr dz)
  8802. {
  8803. int exit_status, n, cc, vc, newcc, pkcnt, thistrof, thispeak, nexttrof, peakcc;
  8804. int preskirt_stt, postskirt_end = 0, nu_preskirt_stt, nu_postskirt_end, skirtlen, offset, famp_param = 0;
  8805. int *ftrn[9];
  8806. float *tranpos[5];
  8807. double skirting, frq, time;
  8808. double ampscale[5];
  8809. skirting = 1.0 - dz->param[F_SINING]; // F_SINING Range 0 (full formant) to 1 (sinusoid, single channel)
  8810. // Width of skirt Range 1 (all of skirt) to 0 (no skirt)
  8811. tranpos[1] = dz->fptr[QOR_FRQ1];
  8812. tranpos[2] = dz->fptr[QOR_FRQ2]; // point to arrays for formant transposition
  8813. tranpos[3] = dz->fptr[QOR_FRQ3];
  8814. tranpos[4] = dz->fptr[QOR_FRQ4];
  8815. ftrn[0] = dz->iparray[F_CHTRAIN1]; // And flbufptr channels of peaks and trofs
  8816. ftrn[1] = dz->iparray[F_CHTRAIN2];
  8817. ftrn[2] = dz->iparray[F_CHTRAIN3];
  8818. ftrn[3] = dz->iparray[F_CHTRAIN4];
  8819. ftrn[4] = dz->iparray[F_CHTRAIN5];
  8820. ftrn[5] = dz->iparray[F_CHTRAIN6];
  8821. ftrn[6] = dz->iparray[F_CHTRAIN7];
  8822. ftrn[7] = dz->iparray[F_CHTRAIN8];
  8823. ftrn[8] = dz->iparray[F_CHTRAIN9];
  8824. ampscale[1] = dz->param[F_AMP1];
  8825. ampscale[2] = dz->param[F_AMP2];
  8826. ampscale[3] = dz->param[F_AMP3];
  8827. ampscale[4] = dz->param[F_AMP4];
  8828. // Array numbering error-check
  8829. n = 0;
  8830. offset = 2;
  8831. for(pkcnt = 1;pkcnt <= 4;pkcnt++) {
  8832. famp_param = pkcnt+offset;
  8833. switch(pkcnt) {
  8834. case(1): if(famp_param != F_AMP1) n = 1; break;
  8835. case(2): if(famp_param != F_AMP2) n = 1; break;
  8836. case(3): if(famp_param != F_AMP3) n = 1; break;
  8837. case(4): if(famp_param != F_AMP4) n = 1; break;
  8838. }
  8839. if(n) {
  8840. fprintf(stdout,"ERROR: Array numbering mismatch: formants_sinus() Change offset, or array numbers.\n");
  8841. return PROGRAM_ERROR;
  8842. }
  8843. }
  8844. // Preset windowbuf to zeroamplitude, and default frequencies
  8845. for(cc = 0, vc = cc*2;cc < dz->clength;cc++,vc+=2) {
  8846. dz->windowbuf[0][AMPP] = 0.0f;
  8847. dz->windowbuf[0][FREQ] = (float)(cc * dz->chwidth);
  8848. }
  8849. pkcnt = 1;
  8850. // Copy transposed peaks (& their skirts) into windowbuf
  8851. for(n = 0;n < PKBLOK-1;n+=2) { // Going up channo-of-trof-peak data in pairs, where peaks are the 2nd items
  8852. thistrof = n;
  8853. thispeak = n+1;
  8854. nexttrof = n+2;
  8855. peakcc = ftrn[thispeak][inner_lpcnt]; // Go to the original cc channel the fpeak data was in
  8856. if(skirting > 0) {
  8857. if(n == 0) // Find the size of the peak skirts which must be transformed
  8858. preskirt_stt = ftrn[thistrof][inner_lpcnt];
  8859. else
  8860. preskirt_stt = postskirt_end;
  8861. postskirt_end = ftrn[nexttrof][inner_lpcnt];
  8862. skirtlen = peakcc - preskirt_stt;
  8863. skirtlen = (int)round(skirtlen * skirting);
  8864. nu_preskirt_stt = peakcc - skirtlen;
  8865. skirtlen = postskirt_end - peakcc;
  8866. skirtlen = (int)round(skirtlen * skirting);
  8867. nu_postskirt_end = peakcc + skirtlen;
  8868. } else {
  8869. nu_preskirt_stt = peakcc;
  8870. nu_postskirt_end = peakcc;
  8871. }
  8872. if(dz->brksize[famp_param]) {
  8873. time = dz->frametime * n;
  8874. if((exit_status = read_value_from_brktable(time,famp_param,dz))<0)
  8875. return exit_status;
  8876. } // For the peak & the remaining skirt channels
  8877. for(cc = nu_preskirt_stt, vc = cc*2;cc <= nu_postskirt_end;cc++,vc+=2) {
  8878. frq = dz->flbufptr[0][FREQ] * tranpos[pkcnt][inner_lpcnt]; // Transpose them,
  8879. newcc = (int)round(frq/(double)dz->chwidth); // put them in approp channel of windowbuf, with their orig amplitude
  8880. // Pre modify level of formants, if params set
  8881. if(ampscale[pkcnt] != 1.0)
  8882. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * ampscale[pkcnt]);
  8883. if(dz->flbufptr[0][AMPP] > dz->windowbuf[0][newcc*2]) { // IF there's not already (new) data in that channel with a higher amplitude
  8884. dz->windowbuf[0][newcc*2] = dz->flbufptr[0][AMPP];
  8885. dz->windowbuf[0][newcc*2+1] = (float)frq;
  8886. }
  8887. }
  8888. pkcnt++;
  8889. }
  8890. // Replace window by transformed window
  8891. memcpy((char *)dz->flbufptr[0],(char *)dz->windowbuf[0],dz->wanted * sizeof(float));
  8892. if(dz->param[FGAIN] > 0.0 && !flteq(dz->param[FGAIN],1.0)) {
  8893. for(vc=0;vc<dz->wanted;vc+=2)
  8894. dz->flbufptr[0][AMPP] = (float)(dz->flbufptr[0][AMPP] * dz->param[FGAIN]);
  8895. }
  8896. return FINISHED;
  8897. }
  8898. /************************** STORE_FORMANT_FRQ_DATA ************************/
  8899. int store_formant_frq_data(int inner_lpcnt,dataptr dz)
  8900. {
  8901. int exit_status, n, pkno, get_fundamental = 0, thistrof, thispeak, nexttrof, pretrof, spstt, spend, ccstt, vcstt, ccend, cc, vc, newcc;
  8902. float frqstt, frqend, the_fundamental = 0.0f, newfrq;
  8903. double maxamp, minamp;
  8904. int *peakat = dz->iparray[PEAKPOS], *ftrn[9];
  8905. float *ffrq[5];
  8906. if(dz->fundamental)
  8907. the_fundamental = dz->pitches[inner_lpcnt];
  8908. peakat += inner_lpcnt * PKBLOK; // Go to current position in peak-data array
  8909. ffrq[1] = dz->fptr[FOR_FRQ1];
  8910. ffrq[2] = dz->fptr[FOR_FRQ2]; // Point to appropriate arrays to store formant frq-data
  8911. ffrq[3] = dz->fptr[FOR_FRQ3];
  8912. ffrq[4] = dz->fptr[FOR_FRQ4];
  8913. ftrn[0] = dz->iparray[F_CHTRAIN1]; // And assciated formant-frq channel in flbufptr[0]
  8914. ftrn[1] = dz->iparray[F_CHTRAIN2];
  8915. ftrn[2] = dz->iparray[F_CHTRAIN3];
  8916. ftrn[3] = dz->iparray[F_CHTRAIN4];
  8917. ftrn[4] = dz->iparray[F_CHTRAIN5]; // And assciated formant-frq channel in flbufptr[0]
  8918. ftrn[5] = dz->iparray[F_CHTRAIN6];
  8919. ftrn[6] = dz->iparray[F_CHTRAIN7];
  8920. ftrn[7] = dz->iparray[F_CHTRAIN8];
  8921. ftrn[8] = dz->iparray[F_CHTRAIN9]; // And assciated formant-frq channel in flbufptr[0]
  8922. for(n = 0,pkno = 1; n < PKBLOK-1; n+=2,pkno++) { // Going through the trof and peaks in pairs
  8923. thistrof = n;
  8924. thispeak = n+1;
  8925. nexttrof = n+2;
  8926. spstt = peakat[n]; // Get specenvamp locations of a trof.
  8927. if(n == 0) {
  8928. if(dz->fundamental && n == 0)
  8929. get_fundamental = 1;
  8930. if(spstt == 0) // Find specenv frqs associated with top and bottom of this trof
  8931. frqstt = 0.0f;
  8932. else
  8933. frqstt = dz->specenvtop[spstt-1];
  8934. frqend = dz->specenvtop[spstt];
  8935. ccstt = (int)floor(frqstt/dz->chwidth);// Find the flbufpr channels associated with these frqs
  8936. ccend = (int)ceil(frqend/dz->chwidth);
  8937. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  8938. vcstt = ccstt * 2;
  8939. ftrn[thistrof][inner_lpcnt] = ccstt;
  8940. for(cc = ccstt,vc = vcstt; cc < ccend; cc++,vc+=2) {
  8941. if(dz->flbufptr[0][AMPP] < minamp) {
  8942. minamp = dz->flbufptr[0][AMPP];
  8943. ftrn[thistrof][inner_lpcnt] = cc;
  8944. }
  8945. }
  8946. }
  8947. pretrof = ftrn[thistrof][inner_lpcnt]; // if n>0, value of nexttrof in last loop pass, becomes thistrof in this pass
  8948. spend = peakat[nexttrof]; // Find specenv location of next TROF
  8949. frqstt = dz->specenvtop[spstt]; // Find the top of the frequency band associated with the lower trof
  8950. frqend = dz->specenvtop[spend - 1]; // Find the bottom of the frequency band associated with the upper trof
  8951. ccstt = (int)floor(frqstt/dz->chwidth); // Find the flbufpr channels associated with these frqs
  8952. ccend = (int)ceil(frqend/dz->chwidth);
  8953. minamp = HUGE; // Find the flbuptr location of minimum amplitude.
  8954. ftrn[nexttrof][inner_lpcnt] = ccstt;
  8955. for(cc = ccstt,vc = ccstt*2; cc < ccend; cc++,vc+=2) {
  8956. if(dz->flbufptr[0][AMPP] < minamp) {
  8957. minamp = dz->flbufptr[0][AMPP];
  8958. ftrn[nexttrof][inner_lpcnt] = cc;
  8959. }
  8960. }
  8961. ccstt = pretrof; // Search between these trofs, for the peak
  8962. ccend = ftrn[nexttrof][inner_lpcnt];
  8963. maxamp = -HUGE; // Find flbufptr location of PEAK amplitude between these trofs
  8964. ftrn[thispeak][inner_lpcnt] = ccstt;
  8965. for(cc = ccstt,vc = ccstt*2; cc < ccend; cc++,vc+=2) {
  8966. if(dz->flbufptr[0][AMPP] > maxamp) {
  8967. maxamp = dz->flbufptr[0][AMPP];
  8968. ffrq[pkno][inner_lpcnt] = dz->flbufptr[0][FREQ];
  8969. ftrn[thispeak][inner_lpcnt] = cc;
  8970. }
  8971. }
  8972. if(get_fundamental) { // If at peak1 and we want to force getting the fundamental (e.g. if adjacent harmonic louder)
  8973. if(the_fundamental > 0.0) {
  8974. if((exit_status = locate_channel_of_fundamental(inner_lpcnt,&newfrq,&newcc,dz))<0)
  8975. return exit_status;
  8976. ffrq[pkno][inner_lpcnt] = newfrq;
  8977. ftrn[thispeak][inner_lpcnt] = newcc;
  8978. }
  8979. get_fundamental = 0; // Only (try to) get fundamental when in first formant
  8980. }
  8981. }
  8982. return FINISHED;
  8983. }
  8984. /************************** PITCHLINE_SMOOTH ************************/
  8985. int pitchline_smooth(float *pichline,int min_wcnt,int ismidi,dataptr dz)
  8986. {
  8987. float previouspitch, thispitch;
  8988. double minpitch;
  8989. int n, m, k, wcnt;
  8990. if(ismidi)
  8991. minpitch = MINPITCHMIDI;
  8992. else
  8993. minpitch = MINPITCH;
  8994. previouspitch = -1;
  8995. wcnt = 0;
  8996. for(n = 0; n < dz->wlength-1; n++) {
  8997. if(pichline[n] < minpitch) // Find the next pitch
  8998. continue; // and start a count of the number of windows it persists for
  8999. thispitch = pichline[n];
  9000. wcnt = 1;
  9001. for(m = n+1; m < dz->wlength; m++) { // Look at block of pitches beyond "thispitch"...
  9002. if(pichline[m] < minpitch) { // If we hit an unpitched area
  9003. if(wcnt < min_wcnt) { // IF there were not enough windows in the block of pitch
  9004. if(previouspitch > 0.0) { // Set them equal to the preceeding pitch (if there is one)
  9005. for(k = n; k < m; k++)
  9006. pichline[k] = previouspitch;
  9007. }
  9008. } else // Else they were a valid block
  9009. previouspitch = thispitch; // Set this pitch up as the previouspitch for next search
  9010. break; // Outer loop will now skip this no-pitch window and proceed
  9011. } // Break to get next pitch;
  9012. if(pichline[m] == thispitch) // If still on same pitch, count it
  9013. wcnt++; // Else
  9014. else {
  9015. if(wcnt < min_wcnt) { // If we don't have valid wcnt for this pitch
  9016. if(previouspitch > 0.0) { // set it equal to the previous pitch
  9017. for(k = n; k < m; k++)
  9018. pichline[k] = previouspitch;
  9019. }
  9020. }
  9021. break; // break to the outer loop
  9022. }
  9023. }
  9024. if(m == dz->wlength) { // If we didn't break from inner loop
  9025. if(wcnt < min_wcnt) { // If last block of pitch doesn't have valid wcnt for this pitch
  9026. if(previouspitch > 0.0) { // set it equal to the previous pitch
  9027. for(k = n; k < m; k++)
  9028. pichline[k] = previouspitch;
  9029. }
  9030. }
  9031. }
  9032. n = m-1; // forces window we've reached to be caught in outer loop
  9033. }
  9034. return FINISHED;
  9035. }
  9036. /************************** SMOOTH_NOTE_TO_NOTE_TRANSITIONS ************************/
  9037. int smooth_note_to_note_transitions(float *pichline,dataptr dz)
  9038. {
  9039. double pitchstep;
  9040. float thispitch;
  9041. int n, m, j, k;
  9042. int glide_wins = (int)round(PCHANGE_DUR/dz->frametime);
  9043. for(n = 0; n < dz->wlength-1; n++) {
  9044. if(pichline[n] < MINPITCH) // Find the next pitch
  9045. continue; // and start a count of the number of windows it persists for
  9046. thispitch = pichline[n];
  9047. for(m = n+1; m < dz->wlength; m++) { // Look at block of pitches beyond "thispitch"...
  9048. if(pichline[m] != thispitch) { // If we hit a new pitch or an unpitched area
  9049. if(pichline[m] > MINPITCH && m > glide_wins) { // if in new pitch area, and enough windows available todo pitch-glide
  9050. pitchstep = pichline[m] - thispitch; // Get step in pitch
  9051. 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
  9052. for(j= 1,k=m-glide_wins;k < m;j++,k++)
  9053. pichline[k] = (float)(pichline[k] + (pitchstep * j));
  9054. }
  9055. break; // break to the outer loop
  9056. }
  9057. }
  9058. n = m-1;
  9059. }
  9060. return FINISHED;
  9061. }
  9062. /************************** OCTAVIATE_TIMED_HF_DATA ************************/
  9063. int octaviate_and_store_timed_hf_data(dataptr dz)
  9064. {
  9065. int n, m, j;
  9066. double *pset = dz->parray[QUANTPITCH], *prepitch = dz->parray[PREPICH];
  9067. double nextpitch;
  9068. double octstep;
  9069. int loc = 0, pitchpos = 0;
  9070. for(n=0;n < dz->bincnt;n++) // Preset the array to max possible quantisation value
  9071. pset[n] = MIDIMAX;
  9072. for(n = 0; n < dz->itemcnt; n++) { // For every line of entries
  9073. if(pitchpos >= dz->bincnt) {
  9074. sprintf(errstr,"Array overflow 1 in octaviate_and_store_timed_hf_data()\n");
  9075. return PROGRAM_ERROR;
  9076. }
  9077. pset[pitchpos++] = prepitch[loc]; // Copy time of pitch-set
  9078. octstep = 0.0;
  9079. for(m=0;m < MIDIOCTSPAN; m++) { // For evey octave in the MIDI range
  9080. for(j = 1;j < dz->quantcnt;j++) { // For every PITCH entry in the line
  9081. nextpitch = prepitch[loc+j] + octstep; // Get entry and add octstep
  9082. nextpitch = min(nextpitch,MIDIMAX);
  9083. if(pitchpos >= dz->bincnt) {
  9084. sprintf(errstr,"Array overflow 2 in octaviate_and_store_timed_hf_data()\n");
  9085. return PROGRAM_ERROR;
  9086. }
  9087. pset[pitchpos++] = nextpitch; // copy new pitch into final array
  9088. }
  9089. octstep += SEMITONES_PER_OCTAVE;
  9090. }
  9091. loc += dz->quantcnt; // Go to next set of original entries
  9092. }
  9093. dz->quantcnt--; // No of quantising items in one timed HF before octaviation
  9094. dz->quantcnt *= MIDIOCTSPAN; // No of quantising items in one timed HF after octaviation
  9095. dz->quantcnt++; // With the time value
  9096. return FINISHED;
  9097. }
  9098. /************************** STRIP_END_SPACE ************************/
  9099. void strip_end_space(char *p)
  9100. {
  9101. char *q = p;
  9102. while(*p != ENDOFSTR)
  9103. p++;
  9104. p--;
  9105. while(isspace(*p)) {
  9106. *p = ENDOFSTR;
  9107. p--;
  9108. if(p == q)
  9109. break;
  9110. }
  9111. return;
  9112. }