libcm is a C development framework with an emphasis on audio signal processing applications.
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmLinkedHeap.h"
  11. #include "cmSymTbl.h"
  12. #include "cmFloatTypes.h"
  13. #include "cmComplexTypes.h"
  14. #include "cmFile.h"
  15. #include "cmFileSys.h"
  16. #include "cmProcObj.h"
  17. #include "cmProcTemplate.h"
  18. #include "cmAudioFile.h"
  19. #include "cmMath.h"
  20. #include "cmProc.h"
  21. #include "cmVectOps.h"
  22. #include "cmKeyboard.h"
  23. #include "cmGnuPlot.h"
  24. #include "cmTime.h"
  25. #include "cmMidi.h"
  26. #include "cmProc2.h"
  27. //------------------------------------------------------------------------------------------------------------
  28. cmArray* cmArrayAllocate( cmCtx* c, cmArray* ap, unsigned eleCnt, unsigned eleByteCnt, unsigned flags )
  29. {
  30. cmArray* p = cmObjAlloc( cmArray, c, ap );
  31. if( eleCnt > 0 && eleByteCnt > 0 )
  32. if( cmArrayInit(p, eleCnt, eleByteCnt, flags ) != cmOkRC )
  33. cmArrayFree(&p);
  34. return cmOkRC;
  35. }
  36. cmRC_t cmArrayFree( cmArray** pp )
  37. {
  38. cmRC_t rc = cmOkRC;
  39. cmArray* p = *pp;
  40. if( pp == NULL || *pp == NULL )
  41. return cmOkRC;
  42. if((rc = cmArrayFinal(p)) != cmOkRC )
  43. return rc;
  44. cmMemPtrFree(&p->ptr);
  45. cmObjFree(pp);
  46. return rc;
  47. }
  48. cmRC_t cmArrayInit( cmArray* p, unsigned eleCnt, unsigned eleByteCnt, unsigned flags )
  49. {
  50. cmRC_t rc = cmOkRC;
  51. if((rc = cmArrayFinal(p)) != cmOkRC )
  52. return rc;
  53. p->allocByteCnt = eleCnt * eleByteCnt;
  54. p->ptr = cmIsFlag(flags,kZeroArrayFl) ? cmMemResizeZ( char, p->ptr, p->allocByteCnt ) : cmMemResize( char, p->ptr, p->allocByteCnt );
  55. p->eleCnt = eleCnt;
  56. p->eleByteCnt = eleByteCnt;
  57. return rc;
  58. }
  59. cmRC_t cmArrayFinal( cmArray* p )
  60. { return cmOkRC; }
  61. char* cmArrayReallocDestroy(cmArray* p, unsigned newEleCnt, unsigned newEleByteCnt, unsigned flags )
  62. {
  63. // if memory is expanding
  64. if( newEleCnt * newEleByteCnt > p->allocByteCnt )
  65. cmArrayInit( p, newEleCnt, newEleByteCnt, flags );
  66. else
  67. {
  68. // ... otherwise memory is contrcmting
  69. p->eleCnt = newEleCnt;
  70. p->eleByteCnt = newEleByteCnt;
  71. if( cmIsFlag( flags, kZeroArrayFl ))
  72. memset(p->ptr,0,p->eleByteCnt);
  73. }
  74. return p->ptr;
  75. }
  76. void cmArrayReallocDestroyV(cmArray* p, int eleByteCnt,unsigned flags, ... )
  77. {
  78. unsigned i;
  79. unsigned eleCnt = 0;
  80. unsigned argCnt = 0;
  81. va_list vl0,vl1;
  82. assert(eleByteCnt>0);
  83. va_start(vl0,flags);
  84. va_copy(vl1,vl0);
  85. while( va_arg(vl0,void**) != NULL )
  86. {
  87. int argEleCnt = va_arg(vl0,int);
  88. assert(argEleCnt>0);
  89. eleCnt += argEleCnt;
  90. ++argCnt;
  91. }
  92. va_end(vl0);
  93. char* a = cmArrayReallocDestroy(p,eleCnt,eleByteCnt,flags);
  94. for(i=0; i<argCnt; ++i)
  95. {
  96. void** vp = va_arg(vl1,void**);
  97. unsigned n = va_arg(vl1,unsigned);
  98. *vp = a;
  99. a += n*eleByteCnt;
  100. }
  101. va_end(vl1);
  102. }
  103. char* cmArrayReallocPreserve(cmArray* p, unsigned newEleCnt, unsigned newEleByteCnt, unsigned flags )
  104. {
  105. unsigned cn = p->eleCnt * p->eleByteCnt;
  106. unsigned dn = newEleCnt * newEleByteCnt;
  107. if( dn > p->allocByteCnt )
  108. p->allocByteCnt = dn;
  109. p->ptr = cmIsFlag(flags,kZeroArrayFl ) ? cmMemResizePZ( char, p->ptr, cn ) : cmMemResizeP( char, p->ptr, cn);
  110. p->eleCnt = newEleCnt;
  111. p->eleByteCnt= newEleByteCnt;
  112. return p->ptr;
  113. }
  114. //------------------------------------------------------------------------------------------------------------
  115. cmAudioFileWr* cmAudioFileWrAlloc( cmCtx* c, cmAudioFileWr* ap, unsigned procSmpCnt, const char* fn, double srate, unsigned chCnt, unsigned bitsPerSample )
  116. {
  117. cmAudioFileWr* p = cmObjAlloc( cmAudioFileWr, c, ap );
  118. if( cmAudioFileWrInit( p, procSmpCnt, fn, srate, chCnt, bitsPerSample ) != cmOkRC )
  119. cmObjFree(&p);
  120. return p;
  121. }
  122. cmRC_t cmAudioFileWrFree( cmAudioFileWr** pp )
  123. {
  124. cmRC_t rc = cmOkRC;
  125. if( pp != NULL && *pp != NULL )
  126. {
  127. cmAudioFileWr* p = *pp;
  128. if((rc = cmAudioFileWrFinal(p)) == cmOkRC )
  129. {
  130. cmMemPtrFree(&p->bufV);
  131. cmMemPtrFree(&p->fn );
  132. cmObjFree(pp);
  133. }
  134. }
  135. return rc;
  136. }
  137. cmRC_t cmAudioFileWrInit( cmAudioFileWr* p, unsigned procSmpCnt, const char* fn, double srate, unsigned chCnt, unsigned bitsPerSample )
  138. {
  139. cmRC_t rc;
  140. cmRC_t afRC;
  141. if((rc = cmAudioFileWrFinal( p)) != cmOkRC )
  142. return rc;
  143. p->h = cmAudioFileNewCreate( fn, srate, bitsPerSample, chCnt, &afRC, p->obj.err.rpt );
  144. if( afRC != kOkAfRC )
  145. return cmCtxRtCondition( &p->obj, afRC, "Unable to open the audio file:'%s'", fn );
  146. p->bufV = cmMemResize( cmSample_t, p->bufV, procSmpCnt * chCnt );
  147. p->procSmpCnt = procSmpCnt;
  148. p->chCnt = chCnt;
  149. p->curChCnt = 0;
  150. p->fn = cmMemResizeZ( cmChar_t, p->fn, strlen(fn)+1 );
  151. strcpy(p->fn,fn);
  152. return rc;
  153. }
  154. cmRC_t cmAudioFileWrFinal( cmAudioFileWr* p )
  155. {
  156. cmRC_t afRC;
  157. if( p != NULL )
  158. {
  159. if( cmAudioFileIsValid( p->h ) )
  160. if(( afRC = cmAudioFileDelete( &p->h )) != kOkAfRC )
  161. return cmCtxRtCondition( &p->obj, afRC, "Unable to close the audio file:'%s'", p->fn );
  162. }
  163. return cmOkRC;
  164. }
  165. cmRC_t cmAudioFileWrExec( cmAudioFileWr* p, unsigned chIdx, const cmSample_t* sp, unsigned sn )
  166. {
  167. cmRC_t afRC;
  168. assert( sn <= p->procSmpCnt && chIdx < p->chCnt );
  169. cmSample_t* buf = p->bufV + (chIdx * p->procSmpCnt);
  170. cmVOS_Copy( buf, sn, sp);
  171. if( sn < p->procSmpCnt )
  172. cmVOS_Fill( buf+sn, p->procSmpCnt-sn, 0 );
  173. p->curChCnt++;
  174. if( p->curChCnt == p->chCnt )
  175. {
  176. p->curChCnt = 0;
  177. cmSample_t* bufPtrPtr[ p->chCnt ];
  178. unsigned i = 0;
  179. for(i=0; i<p->chCnt; ++i)
  180. bufPtrPtr[i] = p->bufV + (i*p->procSmpCnt);
  181. if((afRC = cmAudioFileWriteSample( p->h, p->procSmpCnt, p->chCnt, bufPtrPtr )) != kOkAfRC )
  182. return cmCtxRtCondition( &p->obj, afRC, "Write failed on audio file:'%s'", p->fn );
  183. }
  184. return cmOkRC;
  185. }
  186. void cmAudioFileWrTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  187. {
  188. const char* fn = "/home/kevin/src/cm/test0.aif";
  189. double durSecs = 10;
  190. double srate = 44100;
  191. unsigned chCnt = 2;
  192. unsigned bitsPerSmp = 16;
  193. unsigned procSmpCnt = 64;
  194. double hz = 1000;
  195. unsigned overToneCnt= 1;
  196. unsigned smpCnt = durSecs * srate;
  197. unsigned i;
  198. cmCtx* c = cmCtxAlloc( NULL, rpt, lhH, stH );
  199. cmSigGen* sgp = cmSigGenAlloc( c, NULL, procSmpCnt, srate, kWhiteWfId, hz, overToneCnt );
  200. cmAudioFileWr* awp = cmAudioFileWrAlloc( c, NULL, procSmpCnt, fn, srate, chCnt, bitsPerSmp );
  201. for(i=0; i<smpCnt; ++i)
  202. {
  203. cmSigGenExec( sgp );
  204. cmAudioFileWrExec( awp, 0, sgp->outV, sgp->outN );
  205. cmAudioFileWrExec( awp, 1, sgp->outV, sgp->outN );
  206. i += sgp->outN;
  207. }
  208. printf("Frames:%i\n",smpCnt);
  209. cmAudioFileWrFree(&awp);
  210. cmSigGenFree( &sgp );
  211. cmCtxFree(&c);
  212. cmAudioFileReportFn( fn, 0, 20, rpt );
  213. }
  214. //------------------------------------------------------------------------------------------------------------
  215. cmMatrixBuf* cmMatrixBufAllocFile( cmCtx* c, cmMatrixBuf* p, const char* fn )
  216. {
  217. cmRC_t rc;
  218. cmMatrixBuf* op = cmObjAlloc( cmMatrixBuf, c, p );
  219. if( fn != NULL )
  220. if((rc = cmMatrixBufInitFile(op,fn)) != cmOkRC )
  221. cmObjFree(&op);
  222. return op;
  223. }
  224. cmMatrixBuf* cmMatrixBufAllocCopy(cmCtx* c, cmMatrixBuf* p, unsigned rn, unsigned cn, const cmSample_t* sp )
  225. {
  226. cmRC_t rc;
  227. cmMatrixBuf* op = cmObjAlloc( cmMatrixBuf, c, p );
  228. if( sp != NULL && rn > 0 && cn > 0 )
  229. if((rc = cmMatrixBufInitCopy(op,rn,cn,sp)) != cmOkRC )
  230. cmObjFree(&op);
  231. return op;
  232. }
  233. cmMatrixBuf* cmMatrixBufAlloc( cmCtx* c, cmMatrixBuf* p, unsigned rn, unsigned cn )
  234. {
  235. cmRC_t rc;
  236. cmMatrixBuf* op = cmObjAlloc( cmMatrixBuf, c, p );
  237. if( rn > 0 && cn > 0 )
  238. if((rc = cmMatrixBufInit(op,rn,cn)) != cmOkRC )
  239. cmObjFree(&op);
  240. return op;
  241. }
  242. cmRC_t cmMatrixBufFree( cmMatrixBuf** pp )
  243. {
  244. cmRC_t rc = cmOkRC;
  245. if( pp != NULL && *pp != NULL )
  246. {
  247. cmMatrixBuf* p = *pp;
  248. if((rc = cmMatrixBufFinal(p)) == cmOkRC )
  249. {
  250. cmMemPtrFree(&p->bufPtr);
  251. cmObjFree(pp);
  252. }
  253. }
  254. return rc;
  255. }
  256. void _cmMatrixBufGetFileSize( FILE* fp, unsigned* lineCharCntPtr, unsigned* lineCntPtr )
  257. {
  258. *lineCharCntPtr = 0;
  259. *lineCntPtr = 0;
  260. while( !feof(fp) )
  261. {
  262. char ch;
  263. unsigned charCnt = 0;
  264. while( (ch = getc(fp)) != EOF )
  265. {
  266. charCnt++;
  267. if( ch == '\n' )
  268. break;
  269. }
  270. *lineCntPtr += 1;
  271. if(charCnt > *lineCharCntPtr )
  272. *lineCharCntPtr = charCnt;
  273. }
  274. *lineCharCntPtr += 5; // add a safety margin
  275. }
  276. cmRC_t _cmMatrixBufGetMatrixSize( cmObj* op, FILE* fp, unsigned lineCharCnt, unsigned lineCnt, unsigned* rowCntPtr, unsigned * colCntPtr, const char* fn )
  277. {
  278. unsigned i;
  279. char lineBuf[ lineCharCnt + 1 ];
  280. *rowCntPtr = 0;
  281. *colCntPtr = 0;
  282. for(i=0; i<lineCnt; ++i)
  283. {
  284. if(fgets(lineBuf,lineCharCnt,fp)==NULL)
  285. {
  286. // if the last line is blank then return from here
  287. if( feof(fp) )
  288. return cmOkRC;
  289. return cmCtxRtCondition( op, cmSystemErrorRC, "A read error occured on the matrix file:'%s'.",fn);
  290. }
  291. assert( strlen(lineBuf) < lineCharCnt );
  292. char* lp = lineBuf;
  293. char* tp;
  294. // eat any leading white space
  295. while( (*lp) && isspace(*lp) )
  296. ++lp;
  297. // if the line was blank then skip it
  298. if( strlen(lp) == 0 || *lp == '#' )
  299. continue;
  300. (*rowCntPtr) += 1;
  301. unsigned colCnt;
  302. for(colCnt=0; (tp = strtok(lp," ")) != NULL; ++colCnt )
  303. lp = NULL;
  304. if( colCnt > *colCntPtr )
  305. *colCntPtr = colCnt;
  306. }
  307. return cmOkRC;
  308. }
  309. double _cmMatrixBufStrToNum( cmObj* op, const char* cp )
  310. {
  311. double v;
  312. if( sscanf(cp,"%le ",&v) != 1 )
  313. cmCtxRtCondition( op, cmArgAssertRC, "Parse error reading matrix file.");
  314. return v;
  315. }
  316. cmRC_t _cmMatrixBufReadFile(cmObj* op, FILE* fp, cmSample_t* p, unsigned lineCharCnt, unsigned rn, unsigned cn)
  317. {
  318. char lineBuf[ lineCharCnt+1 ];
  319. unsigned ci = 0;
  320. unsigned ri = 0;
  321. while( fgets(lineBuf,lineCharCnt,fp) != NULL )
  322. {
  323. char* lp = lineBuf;
  324. char* tp;
  325. while( (*lp) && isspace(*lp) )
  326. lp++;
  327. if( strlen(lp) == 0 || *lp == '#' )
  328. continue;
  329. for(ci=0; (tp = strtok(lp," ")) != NULL; ++ci )
  330. {
  331. p[ (ci*rn) + ri ] = _cmMatrixBufStrToNum(op,tp); //atof(tp);
  332. lp = NULL;
  333. }
  334. ++ri;
  335. }
  336. return cmOkRC;
  337. }
  338. cmRC_t cmMatrixBufInitFile( cmMatrixBuf* p, const char* fn )
  339. {
  340. cmRC_t rc;
  341. FILE* fp;
  342. unsigned lineCharCnt;
  343. unsigned lineCnt;
  344. unsigned rn;
  345. unsigned cn;
  346. if((fp = fopen(fn,"rt")) == NULL )
  347. return cmCtxRtCondition( &p->obj, cmSystemErrorRC, "Unable to open the matrix file:'%s'", fn );
  348. // get the length of the longest line in the file
  349. _cmMatrixBufGetFileSize(fp,&lineCharCnt,&lineCnt);
  350. rewind(fp);
  351. // get the count of matrix rows and columns
  352. if((rc=_cmMatrixBufGetMatrixSize( &p->obj, fp, lineCharCnt, lineCnt, &rn, &cn, fn )) != cmOkRC )
  353. goto errLabel;
  354. rewind(fp);
  355. // allocate the matrix memory
  356. cmMatrixBufInit(p,rn,cn);
  357. // fill the matrix from the file
  358. rc = _cmMatrixBufReadFile(&p->obj,fp,p->bufPtr,lineCharCnt,rn,cn);
  359. errLabel:
  360. if( rc != cmOkRC )
  361. cmMatrixBufFinal(p);
  362. fclose(fp);
  363. return rc;
  364. }
  365. cmRC_t cmMatrixBufInitCopy( cmMatrixBuf* p, unsigned rn, unsigned cn, const cmSample_t* sp )
  366. {
  367. cmRC_t rc;
  368. if((rc = cmMatrixBufInit(p,rn,cn)) != cmOkRC )
  369. return rc;
  370. cmVOS_Copy(p->bufPtr,(rn*cn),sp);
  371. return rc;
  372. }
  373. cmRC_t cmMatrixBufInit( cmMatrixBuf* p, unsigned rn, unsigned cn )
  374. {
  375. cmRC_t rc;
  376. if((rc = cmMatrixBufFinal(p)) != cmOkRC )
  377. return rc;
  378. p->rn = rn;
  379. p->cn = cn;
  380. p->bufPtr = cmMemResize( cmSample_t, p->bufPtr, rn*cn );
  381. return cmOkRC;
  382. }
  383. cmRC_t cmMatrixBufFinal( cmMatrixBuf* p )
  384. { return cmOkRC; }
  385. cmSample_t* cmMatrixBufColPtr( cmMatrixBuf* p, unsigned ci )
  386. { assert(ci<p->cn); return p->bufPtr + (ci * p->rn); }
  387. cmSample_t* cmMatrixBufRowPtr( cmMatrixBuf* p, unsigned ri )
  388. { assert(ri<p->rn); return p->bufPtr + ri; }
  389. void cmMatrixBufTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  390. {
  391. cmSample_t v[] = {1,2,2,3};
  392. cmCtx* c = cmCtxAlloc(NULL,rpt,lhH,stH);
  393. cmMatrixBuf* mbp = cmMatrixBufAllocFile(c, NULL, "temp.mat" );
  394. cmMatrixBuf* vbp = cmMatrixBufAllocCopy(c, NULL, 4,1,v);
  395. unsigned i;
  396. printf("rn:%i cn:%i\n",mbp->rn,mbp->cn);
  397. //cmVOS_Print( stdout, 10, 10, mbp->bufPtr );
  398. printf("%.1f\n ",cmVOS_Median( cmMatrixBufColPtr(vbp,0),vbp->rn));
  399. for(i=0; i<mbp->cn; ++i)
  400. {
  401. //cmVOS_Print( stdout, 1, mbp->cn, cmMatrixBufColPtr(c,mbp,i) );
  402. printf("%.1f, ",cmVOS_Median( cmMatrixBufColPtr(mbp,i),mbp->rn));
  403. }
  404. printf("\n");
  405. cmMatrixBufFree(&mbp);
  406. cmMatrixBufFree(&vbp);
  407. cmCtxFree(&c);
  408. }
  409. //------------------------------------------------------------------------------------------------------------
  410. cmSigGen* cmSigGenAlloc( cmCtx* c, cmSigGen* p, unsigned procSmpCnt, double srate, unsigned wfId, double fundFrqHz, unsigned overToneCnt )
  411. {
  412. cmSigGen* op = cmObjAlloc( cmSigGen, c, p );
  413. if( procSmpCnt > 0 && srate > 0 && wfId != kInvalidWfId )
  414. if( cmSigGenInit( op, procSmpCnt, srate, wfId, fundFrqHz, overToneCnt ) != cmOkRC )
  415. cmObjFree(&op);
  416. return op;
  417. }
  418. cmRC_t cmSigGenFree( cmSigGen** pp )
  419. {
  420. cmRC_t rc = cmOkRC;
  421. if( pp != NULL && *pp != NULL )
  422. {
  423. cmSigGen* p = *pp;
  424. if((rc = cmSigGenFinal(p)) == cmOkRC )
  425. {
  426. cmMemPtrFree(&p->outV);
  427. cmObjFree(pp);
  428. }
  429. }
  430. return rc;
  431. }
  432. cmRC_t cmSigGenInit( cmSigGen* p, unsigned procSmpCnt, double srate, unsigned wfId, double fundFrqHz, unsigned overToneCnt )
  433. {
  434. assert( srate > 0 && procSmpCnt > 0 );
  435. p->outV = cmMemResize( cmSample_t, p->outV, procSmpCnt );
  436. p->outN = procSmpCnt;
  437. p->wfId = wfId;
  438. p->overToneCnt = overToneCnt;
  439. p->fundFrqHz = fundFrqHz;
  440. p->phase = 0;
  441. p->delaySmp = 0;
  442. p->srate = srate;
  443. return cmOkRC;
  444. }
  445. cmRC_t cmSigGenFinal( cmSigGen* p )
  446. { return cmOkRC; }
  447. cmRC_t cmSigGenExec( cmSigGen* p )
  448. {
  449. switch( p->wfId )
  450. {
  451. case kSineWfId: p->phase = cmVOS_SynthSine( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz ); break;
  452. case kCosWfId: p->phase = cmVOS_SynthCosine( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz ); break;
  453. case kSquareWfId: p->phase = cmVOS_SynthSquare( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz, p->overToneCnt ); break;
  454. case kTriangleWfId: p->phase = cmVOS_SynthTriangle( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz, p->overToneCnt ); break;
  455. case kSawtoothWfId: p->phase = cmVOS_SynthSawtooth( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz, p->overToneCnt ); break;
  456. case kWhiteWfId: cmVOS_Random( p->outV, p->outN, -1.0, 1.0 ); break;
  457. case kPinkWfId: p->delaySmp = cmVOS_SynthPinkNoise(p->outV, p->outN, p->delaySmp ); break;
  458. case kPulseWfId: p->phase = cmVOS_SynthPulseCos( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz, p->overToneCnt ); break;
  459. case kImpulseWfId: p->phase = cmVOS_SynthImpulse( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz ); break;
  460. case kSilenceWfId: cmVOS_Fill( p->outV, p->outN, 0 ); break;
  461. case kPhasorWfId: p->phase = cmVOS_SynthPhasor( p->outV, p->outN, p->phase, p->srate, p->fundFrqHz ); break;
  462. case kSeqWfId: p->phase = cmVOS_Seq( p->outV, p->outN, p->phase, 1 ); break;
  463. case kInvalidWfId:
  464. default:
  465. return cmCtxRtAssertFailed( &p->obj, 0, "Invalid waveform shape.");
  466. }
  467. return cmOkRC;
  468. }
  469. //------------------------------------------------------------------------------------------------------------
  470. cmDelay* cmDelayAlloc( cmCtx* c, cmDelay* ap, unsigned procSmpCnt, unsigned delaySmpCnt )
  471. {
  472. cmDelay* p = cmObjAlloc( cmDelay, c, ap );
  473. if( procSmpCnt > 0 && delaySmpCnt > 0 )
  474. if( cmDelayInit( p,procSmpCnt,delaySmpCnt) != cmOkRC && ap == NULL )
  475. cmObjFree(&p);
  476. return p;
  477. }
  478. cmRC_t cmDelayFree( cmDelay** pp )
  479. {
  480. cmRC_t rc = cmOkRC;
  481. if( pp != NULL && *pp != NULL )
  482. {
  483. cmDelay* p = *pp;
  484. if((rc = cmDelayFinal(*pp)) == cmOkRC )
  485. {
  486. cmMemPtrFree(&p->bufPtr);
  487. cmObjFree(pp);
  488. }
  489. }
  490. return rc;
  491. }
  492. cmRC_t cmDelayInit( cmDelay* p, unsigned procSmpCnt, unsigned delaySmpCnt )
  493. {
  494. p->procSmpCnt = procSmpCnt;
  495. p->delaySmpCnt = delaySmpCnt;
  496. p->bufSmpCnt = delaySmpCnt + procSmpCnt;
  497. p->bufPtr = cmMemResizeZ( cmSample_t, p->bufPtr, p->bufSmpCnt);
  498. p->delayInIdx = 0;
  499. p->outCnt = 1;
  500. p->outV[0] = p->bufPtr;
  501. p->outN[0] = p->procSmpCnt;
  502. p->outV[1] = NULL;
  503. p->outN[1] = 0;
  504. return cmOkRC;
  505. }
  506. cmRC_t cmDelayFinal( cmDelay* p )
  507. { return cmOkRC; }
  508. cmRC_t cmDelayCopyIn( cmDelay* p, const cmSample_t* sp, unsigned sn )
  509. {
  510. assert(sn<=p->procSmpCnt);
  511. unsigned n0 = cmMin(sn,p->bufSmpCnt - p->delayInIdx);
  512. // copy as many samples as possible from the input to the delayInIdx
  513. cmVOS_Copy(p->bufPtr + p->delayInIdx, n0, sp);
  514. p->delayInIdx = (p->delayInIdx + n0) % p->bufSmpCnt;
  515. // if there was not enough room to copy all the samples into the end of the buffer ....
  516. if( n0 < sn )
  517. {
  518. assert( p->delayInIdx == 0 );
  519. // ... then copy the rest to the beginning of the buffer
  520. unsigned n1 = sn - n0;
  521. cmVOS_Copy(p->bufPtr,n1, sp + n0 );
  522. p->delayInIdx = (p->delayInIdx + n1) % p->bufSmpCnt;
  523. }
  524. return cmOkRC;
  525. }
  526. cmRC_t cmDelayAdvance( cmDelay* p, unsigned sn )
  527. {
  528. // advance the output by sn and make sn samples available
  529. int delayOutIdx = ((p->outV[0] - p->bufPtr) + sn) % p->bufSmpCnt;
  530. p->outV[0] = p->bufPtr + delayOutIdx;
  531. p->outN[0] = cmMin(p->bufSmpCnt - delayOutIdx , sn );
  532. p->outCnt = p->outN[0] == sn ? 1 : 2 ;
  533. p->outV[1] = p->outCnt == 1 ? NULL : p->bufPtr;
  534. p->outN[1] = p->outCnt == 1 ? 0 : sn - p->outN[0];
  535. return cmOkRC;
  536. }
  537. cmRC_t cmDelayExec( cmDelay* p, const cmSample_t* sp, unsigned sn, bool bypassFl )
  538. {
  539. cmRC_t rc = cmOkRC;
  540. if( bypassFl )
  541. memcpy(p->outV,sp,sn*sizeof(cmSample_t));
  542. else
  543. {
  544. cmDelayCopyIn(p,sp,sn);
  545. rc = cmDelayAdvance(p,sn);
  546. }
  547. return rc;
  548. }
  549. void cmDelayTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  550. {
  551. cmCtx ctx;
  552. cmDelay delay;
  553. cmSigGen sigGen;
  554. unsigned procCnt = 4;
  555. unsigned procSmpCnt = 5;
  556. unsigned delaySmpCnt = 3;
  557. unsigned i;
  558. cmCtx* c = cmCtxAlloc( &ctx, rpt, lhH, stH );
  559. cmDelay* dlp = cmDelayAlloc( c, &delay, procSmpCnt, delaySmpCnt );
  560. cmSigGen* sgp = cmSigGenAlloc( c, &sigGen, procSmpCnt, 0, kSeqWfId,0, 0);
  561. for(i=0; i<procCnt; ++i)
  562. {
  563. cmSigGenExec(sgp);
  564. cmDelayExec(dlp,sgp->outV,sgp->outN,false);
  565. //cmVOS_Print( c->outFp, 1, sgp->outN, sgp->outV, 5, 0 );
  566. cmCtxPrint(c,"%i %i : ",i,0);
  567. cmVOS_PrintE( rpt, 1, dlp->outN[0], dlp->outV[0] );
  568. if( dlp->outN[1] > 0 )
  569. {
  570. cmCtxPrint(c,"%i %i : ",i,1);
  571. cmVOS_PrintE( rpt, 1, dlp->outN[1], dlp->outV[1] );
  572. }
  573. }
  574. cmSigGenFinal(sgp);
  575. cmDelayFinal(dlp);
  576. cmCtxFinal(c);
  577. }
  578. //------------------------------------------------------------------------------------------------------------
  579. cmFIR* cmFIRAllocKaiser(cmCtx* c, cmFIR* p, unsigned procSmpCnt, double srate, double passHz, double stopHz, double passDb, double stopDb, unsigned flags )
  580. {
  581. cmFIR* op = cmObjAlloc( cmFIR, c, p );
  582. if( procSmpCnt > 0 && srate > 0 )
  583. if( cmFIRInitKaiser(op,procSmpCnt,srate,passHz,stopHz,passDb,stopDb,flags) != cmOkRC )
  584. cmObjFree(&op);
  585. return op;
  586. }
  587. cmFIR* cmFIRAllocSinc( cmCtx* c, cmFIR* p, unsigned procSmpCnt, double srate, unsigned sincSmpCnt, double fcHz, unsigned flags, const double* wndV )
  588. {
  589. cmFIR* op = cmObjAlloc( cmFIR, c, p );
  590. if( srate > 0 && sincSmpCnt > 0 )
  591. if( cmFIRInitSinc(op,procSmpCnt,srate,sincSmpCnt,fcHz,flags,wndV) != cmOkRC )
  592. cmObjFree(&op);
  593. return op;
  594. }
  595. cmRC_t cmFIRFree( cmFIR** pp )
  596. {
  597. cmRC_t rc = cmOkRC;
  598. if( pp != NULL && *pp != NULL)
  599. {
  600. cmFIR* p = *pp;
  601. if((rc = cmFIRFinal(*pp)) == cmOkRC )
  602. {
  603. cmMemPtrFree(&p->coeffV);
  604. cmMemPtrFree(&p->outV);
  605. cmMemPtrFree(&p->delayV);
  606. cmObjFree(pp);
  607. }
  608. }
  609. return rc;
  610. }
  611. cmRC_t cmFIRInitKaiser( cmFIR* p, unsigned procSmpCnt, double srate, double passHz, double stopHz, double passDb, double stopDb, unsigned flags )
  612. {
  613. // pass/stop frequencies above nyquist produce incorrect results
  614. assert( passHz <= srate/2 && stopHz<=srate/2);
  615. // based on Orfandis, Introduction to Signal Processing, p.551 Prentice Hall, 1996
  616. double fcHz = (passHz + stopHz) / 2; // fc is half way between passHz and stopHz
  617. double dHz = fabs(stopHz-passHz);
  618. // convert ripple spec from db to linear
  619. double dPass = (pow(10,passDb/20)-1) / (pow(10,passDb/20)+1);
  620. double dStop = pow(10,-stopDb/20);
  621. // in practice the ripple must be equal in the stop and pass band - so take the minimum between the two
  622. double d = cmMin(dPass,dStop);
  623. // convert the ripple back to db
  624. double A = -20 * log10(d);
  625. // compute the kaiser alpha coeff
  626. double alpha = 0;
  627. if( A >= 50.0 ) // for ripple > 50
  628. alpha = 0.1102 * (A-8.7);
  629. else // for ripple <= 21
  630. {
  631. if( A > 21 )
  632. alpha = (0.5842 * (pow(A-21.0,0.4))) + (0.07886*(A-21));
  633. }
  634. double D = 0.922;
  635. if( A > 21 )
  636. D = (A - 7.95) / 14.36;
  637. // compute the filter order
  638. unsigned N = (unsigned)(floor(D * srate / dHz) + 1);
  639. //if N is even
  640. if( cmIsEvenU(N) )
  641. N = N + 1;
  642. //printf("fc=%f df=%f dPass=%f dStop=%f d=%f alpha=%f A=%f D=%f N=%i\n",fcHz,dHz,dPass,dStop,d,alpha,A,D,N);
  643. // compute a kaiser function to truncate the sinc
  644. double wnd[ N ];
  645. cmVOD_Kaiser( wnd, N, alpha );
  646. // form an ideal FIR LP impulse response based on a sinc function
  647. cmFIRInitSinc(p,procSmpCnt,srate,N,fcHz,flags, wnd);
  648. //cmVOD_Print(stdout,1,p->coeffCnt,p->coeffV);
  649. return cmOkRC;
  650. }
  651. cmRC_t cmFIRInitSinc( cmFIR* p, unsigned procSmpCnt, double srate, unsigned sincSmpCnt, double fcHz, unsigned flags, const double* wndV )
  652. {
  653. cmRC_t rc;
  654. if((rc = cmFIRFinal(p)) != cmOkRC )
  655. return rc;
  656. p->coeffCnt = sincSmpCnt;
  657. p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt );
  658. p->outN = procSmpCnt;
  659. p->coeffV = cmMemResizeZ( double, p->coeffV, p->coeffCnt );
  660. p->delayV = cmMemResizeZ( double, p->delayV, p->coeffCnt-1 ); // there is always one less delay than coeff
  661. p->delayIdx = 0;
  662. unsigned lp_flags = kNormalize_LPSincFl;
  663. lp_flags |= cmIsFlag(flags,kHighPassFIRFl) ? kHighPass_LPSincFl : 0;
  664. cmVOD_LP_Sinc(p->coeffV, p->coeffCnt, wndV, srate, fcHz, lp_flags );
  665. return cmOkRC;
  666. }
  667. cmRC_t cmFIRFinal( cmFIR* p )
  668. { return cmOkRC; }
  669. cmRC_t cmFIRExec( cmFIR* p, const cmSample_t* sbp, unsigned sn )
  670. {
  671. unsigned delayCnt = p->coeffCnt-1;
  672. int di = p->delayIdx;
  673. const cmSample_t* sep = sbp + sn;
  674. cmSample_t* op = p->outV;
  675. assert( di < delayCnt );
  676. assert( sn <= p->outN );
  677. // for each input sample
  678. while( sbp < sep )
  679. {
  680. // advance the delay line
  681. p->delayIdx = (p->delayIdx + 1) % delayCnt;
  682. const double* cbp = p->coeffV;
  683. const double* cep = cbp + p->coeffCnt;
  684. // mult input sample by coeff[0]
  685. double v = *sbp * *cbp++;
  686. // calc the output sample
  687. while( cbp<cep)
  688. {
  689. // note that the delay is being iterated backwards
  690. if( di == -1 )
  691. di=delayCnt-1;
  692. v += *cbp++ * p->delayV[di];
  693. --di;
  694. }
  695. // store the output sample
  696. *op++ = v;
  697. // insert the input sample
  698. p->delayV[ p->delayIdx ] = *sbp++;
  699. // store the position of the newest ele in the delay line
  700. di = p->delayIdx;
  701. }
  702. return cmOkRC;
  703. }
  704. void cmFIRTest0( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  705. {
  706. unsigned N = 512;
  707. cmKbRecd kb;
  708. cmCtx c;
  709. cmCtxInit(&c,rpt,lhH,stH);
  710. double srate = N;
  711. unsigned procSmpCnt = N;
  712. cmPlotSetup("Test Proc Impl",2,1);
  713. cmSample_t in[ procSmpCnt ];
  714. cmVOS_Fill(in,procSmpCnt,0);
  715. in[0] = 1;
  716. cmVOS_Random(in,procSmpCnt, -1.0, 1.0 );
  717. cmFIR* ffp = cmFIRAllocKaiser( &c, NULL, procSmpCnt,srate, srate*0.025, srate/2, 10, 60, 0 );
  718. //cmFIR* ffp = cmFIRAllocSinc( &c, NULL, 32, 1000, 0 );
  719. cmFftSR* ftp = cmFftAllocSR( &c, NULL, ffp->outV, ffp->outN, kToPolarFftFl );
  720. cmFIRExec( ffp, in, procSmpCnt );
  721. cmFftExecSR( ftp, NULL, 0 );
  722. cmVOR_AmplitudeToDb(ftp->magV,ftp->binCnt,ftp->magV);
  723. printf("coeff cnt:%i\n",ffp->coeffCnt );
  724. cmPlotClear();
  725. cmPlotLineR( "test", NULL, ftp->magV, NULL, ftp->binCnt, NULL, kSolidPlotLineId );
  726. cmPlotDraw();
  727. cmKeyPress(&kb);
  728. cmFftFreeSR(&ftp);
  729. cmFIRFree(&ffp);
  730. }
  731. void cmFIRTest1( cmCtx* ctx )
  732. {
  733. const char* sfn = "/home/kevin/temp/sig.va";
  734. const char* ffn = "/home/kevin/temp/fir.va";
  735. unsigned N = 44100;
  736. unsigned srate = N;
  737. unsigned procSmpCnt = N;
  738. double passHz = 15000;
  739. double stopHz = 14000;
  740. double passDb = 1.0;
  741. double stopDb = 60.0;
  742. unsigned flags = kHighPassFIRFl;
  743. cmSample_t x[ procSmpCnt ];
  744. cmVOS_Fill(x,procSmpCnt,0);
  745. x[0] = 1;
  746. cmVOS_Random(x,procSmpCnt, -1.0, 1.0 );
  747. cmFIR* f = cmFIRAllocKaiser( ctx, NULL, procSmpCnt, srate, passHz, stopHz, stopDb, passDb, flags );
  748. cmFIRExec( f, x, procSmpCnt );
  749. cmVectArrayWriteMatrixS(ctx, ffn, f->outV, 1, f->outN );
  750. cmVectArrayWriteMatrixS(ctx, sfn, x, 1, N );
  751. cmFIRFree(&f);
  752. }
  753. //------------------------------------------------------------------------------------------------------------
  754. cmFuncFilter* cmFuncFilterAlloc( cmCtx* c, cmFuncFilter* p, unsigned procSmpCnt, cmFuncFiltPtr_t funcPtr, void* userPtr, unsigned wndSmpCnt )
  755. {
  756. cmRC_t rc;
  757. cmFuncFilter* op = cmObjAlloc( cmFuncFilter,c, p );
  758. if( procSmpCnt > 0 && funcPtr != NULL && wndSmpCnt > 0 )
  759. {
  760. if( cmShiftBufAlloc(c,&p->shiftBuf,0,0,0) != NULL )
  761. if((rc = cmFuncFilterInit(op,procSmpCnt,funcPtr,userPtr,wndSmpCnt)) != cmOkRC )
  762. {
  763. cmShiftBuf* sbp = &p->shiftBuf;
  764. cmShiftBufFree(&sbp);
  765. cmObjFree(&op);
  766. }
  767. }
  768. return op;
  769. }
  770. cmRC_t cmFuncFilterFree( cmFuncFilter** pp )
  771. {
  772. cmRC_t rc = cmOkRC;
  773. if( pp!=NULL && *pp != NULL )
  774. {
  775. cmFuncFilter* p = *pp;
  776. if((rc = cmFuncFilterFinal(*pp)) == cmOkRC )
  777. {
  778. cmShiftBuf* sbp = &p->shiftBuf;
  779. cmShiftBufFree(&sbp);
  780. cmMemPtrFree(&p->outV);
  781. cmObjFree(pp);
  782. }
  783. }
  784. return rc;
  785. }
  786. cmRC_t cmFuncFilterInit( cmFuncFilter* p, unsigned procSmpCnt, cmFuncFiltPtr_t funcPtr, void* userPtr, unsigned wndSmpCnt )
  787. {
  788. cmRC_t rc;
  789. if(( rc = cmFuncFilterFinal(p)) != cmOkRC )
  790. return rc;
  791. // The shift buffer always consits of the p->wndSmpCnt-1 samples from the previous
  792. // exec followed by the latest procSmpCnt samples at the end of the buffer
  793. cmShiftBufInit( &p->shiftBuf, procSmpCnt, wndSmpCnt + procSmpCnt - 1, procSmpCnt );
  794. p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt);
  795. p->outN = procSmpCnt;
  796. p->funcPtr = funcPtr;
  797. p->curWndSmpCnt = 1;
  798. p->wndSmpCnt = wndSmpCnt;
  799. return rc;
  800. }
  801. cmRC_t cmFuncFilterFinal( cmFuncFilter* p )
  802. { return cmOkRC; }
  803. cmRC_t cmFuncFilterExec( cmFuncFilter* p, const cmSample_t* sp, unsigned sn )
  804. {
  805. assert( sn <= p->outN);
  806. // The window used by this function is always causal. At the very beginning of the signal
  807. // the window length begins at 1 and increases until is has the length p->wndSmpCnt.
  808. // Note that this approach ignores any zeros automatically prepended to the beginning of the
  809. // signal by the shift buffer. The first window processed always has a length of 1 and
  810. // begins with the first actual sample given to the shift buffer. Successive windows increase
  811. // by one and start at the first actual sample until the full window length is available
  812. // from the shift buffer. At this point the window length remains constant and it is hopped
  813. // by one sample for each window.
  814. while(cmShiftBufExec(&p->shiftBuf,sp,sn))
  815. {
  816. const cmSample_t* fsp = p->shiftBuf.outV;
  817. cmSample_t* dp = p->outV;
  818. cmSample_t* ep = p->outV + sn; // produce as many output values as there are input samples
  819. // for each output sample
  820. while( dp < ep )
  821. {
  822. // the source range should never extend outside the shift buffer
  823. assert( fsp + p->curWndSmpCnt <= p->shiftBuf.outV + p->shiftBuf.wndSmpCnt );
  824. // calc the next output value
  825. *dp++ = p->funcPtr( fsp, p->curWndSmpCnt, p->userPtr );
  826. // if the window has not yet achieved its full length ...
  827. if( p->curWndSmpCnt < p->wndSmpCnt )
  828. ++p->curWndSmpCnt; // ... then increase its length by 1
  829. else
  830. ++fsp; // ... otherwise shift it ahead by 1
  831. }
  832. }
  833. return cmOkRC;
  834. }
  835. cmSample_t cmFuncFiltTestFunc( const cmSample_t* sp, unsigned sn, void* vp )
  836. {
  837. //printf("% f % f %p % i\n",*sp,*sp+(sn-1),sp,sn);
  838. cmSample_t v = cmVOS_Median(sp,sn);
  839. printf("%f ",v);
  840. return v;
  841. //return *sp;
  842. }
  843. void cmFuncFilterTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  844. {
  845. unsigned procSmpCnt = 1;
  846. unsigned N = 32;
  847. cmSample_t v[N];
  848. cmCtx c;
  849. unsigned i;
  850. cmCtxAlloc(&c,rpt,lhH,stH);
  851. cmVOS_Seq(v,N,0,1);
  852. cmVOS_Print(rpt,1,32,v);
  853. cmFuncFilter* ffp = NULL;
  854. ffp = cmFuncFilterAlloc( &c, NULL, procSmpCnt, cmFuncFiltTestFunc, NULL, 5 );
  855. for(i=0; i<N; ++i)
  856. cmFuncFilterExec(ffp,v+(i*procSmpCnt),procSmpCnt);
  857. cmFuncFilterFree( &ffp );
  858. cmCtxFinal(&c);
  859. //unsigned v1n = 9;
  860. //cmSample_t v1[9] = { 1, 75, 91, 35, 6, 80, 40, 91, 79};
  861. //cmSample_t v1[10] = {53, 64, 48, 78, 30, 59, 7, 50, 71, 53 };
  862. //printf("Median: %f \n",cmVOS_Median(v1,v1+v1n));
  863. }
  864. //------------------------------------------------------------------------------------------------------------
  865. cmDhmm* cmDhmmAlloc( cmCtx* c, cmDhmm* ap, unsigned stateN, unsigned symN, cmReal_t* initV, cmReal_t* transM, cmReal_t* stsM )
  866. {
  867. cmDhmm* p = cmObjAlloc( cmDhmm, c, ap );
  868. if( stateN > 0 && symN > 0 )
  869. if( cmDhmmInit(p, stateN, symN, initV, transM, stsM ) != cmOkRC )
  870. cmObjFree(&p);
  871. return p;
  872. }
  873. cmRC_t cmDhmmFree( cmDhmm** pp )
  874. {
  875. cmRC_t rc = cmOkRC;
  876. cmDhmm* p = *pp;
  877. if( pp==NULL || *pp==NULL )
  878. return cmOkRC;
  879. if((rc = cmDhmmFinal(p)) != cmOkRC )
  880. return cmOkRC;
  881. cmObjFree(pp);
  882. return rc;
  883. }
  884. cmRC_t cmDhmmInit( cmDhmm* p, unsigned stateN, unsigned symN, cmReal_t* initV, cmReal_t* transM, cmReal_t* stsM )
  885. {
  886. cmRC_t rc;
  887. if((rc = cmDhmmFinal(p)) != cmOkRC )
  888. return rc;
  889. p->stateN = stateN;
  890. p->symN = symN;
  891. p->initV = initV;
  892. p->transM = transM;
  893. p->stsM = stsM;
  894. return cmOkRC;
  895. }
  896. cmRC_t cmDhmmFinal( cmDhmm* p )
  897. { return cmOkRC; }
  898. cmRC_t cmDhmmExec( cmDhmm* p )
  899. {
  900. return cmOkRC;
  901. }
  902. // Generate a random matrix with rows that sum to 1.0.
  903. void _cmDhmmGenRandMatrix( cmReal_t* dp, unsigned rn, unsigned cn )
  904. {
  905. cmReal_t v[ cn ];
  906. unsigned i,j;
  907. for(i=0; i<rn; ++i)
  908. {
  909. cmVOR_Random( v, cn, 0.0, 1.0 );
  910. cmVOR_NormalizeProbability( v, cn);
  911. for(j=0; j<cn; ++j)
  912. dp[ (j * rn) + i ] = v[j];
  913. }
  914. }
  915. enum { kEqualProbHmmFl=0x01, kRandProbHmmFl=0x02, kManualProbHmmFl=0x04 };
  916. void _cmDhmmGenProb( cmReal_t* dp, unsigned rn, unsigned cn, unsigned flags, const cmReal_t* sp )
  917. {
  918. switch( flags )
  919. {
  920. case kRandProbHmmFl:
  921. _cmDhmmGenRandMatrix( dp, rn, cn );
  922. break;
  923. case kEqualProbHmmFl:
  924. {
  925. // equal prob
  926. cmReal_t pr = 1.0/cn;
  927. unsigned i,j;
  928. for(i=0; i<rn; ++i)
  929. for(j=0; j<cn; ++j)
  930. dp[ (j*rn) + i ] = pr;
  931. }
  932. break;
  933. case kManualProbHmmFl:
  934. cmVOR_Copy( dp, (rn*cn), sp );
  935. break;
  936. default:
  937. assert(0);
  938. }
  939. }
  940. // generate a random integer in the range 0 to probN-1 where probV[ probN ] contains
  941. // the probability of generating each of the possible values.
  942. unsigned _cmDhmmGenRandInt( const cmReal_t* probV, unsigned probN, unsigned stride )
  943. {
  944. cmReal_t tmp[ probN ];
  945. cmReal_t cumSumV[ probN+1 ];
  946. const cmReal_t* sp = probV;
  947. cumSumV[0] = 0;
  948. if( stride > 1 )
  949. {
  950. cmVOR_CopyStride( tmp, probN, probV, stride );
  951. sp = tmp;
  952. }
  953. cmVOR_CumSum( cumSumV+1, probN, sp );
  954. return cmVOR_BinIndex( cumSumV, probN+1, (cmReal_t)rand()/RAND_MAX );
  955. }
  956. cmRC_t cmDhmmGenObsSequence( cmDhmm* p, unsigned* dbp, unsigned dn )
  957. {
  958. const unsigned* dep = dbp + dn;
  959. // generate the first state based on the init state prob. vector
  960. unsigned state = _cmDhmmGenRandInt( p->initV, p->stateN, 1 );
  961. // generate an observation from the state based on the symbol prob. vector
  962. *dbp++ = _cmDhmmGenRandInt( p->stsM + state, p->symN, p->stateN );
  963. while( dbp < dep )
  964. {
  965. // get the next state based on the previous state
  966. state = _cmDhmmGenRandInt( p->transM + state, p->stateN, p->stateN );
  967. // given a state generate an observation
  968. *dbp++ = _cmDhmmGenRandInt( p->stsM + state, p->symN, p->stateN );
  969. }
  970. return cmOkRC;
  971. }
  972. /// Perform a forward evaluation of the model given a set of observations.
  973. /// initPrV[ stateN ] is the probability of the model being in each state at the start of the evaluation.
  974. /// alphaM[ stateN, obsN ] is a return value and represents the probability of seeing each symbol at each time step.
  975. enum { kNoLogScaleHmmFl = 0x00, kLogScaleHmmFl = 0x01 };
  976. cmRC_t cmDHmmForwardEval( cmDhmm* p, const cmReal_t* initPrV, const unsigned* obsV, unsigned obsN, cmReal_t* alphaM, unsigned flags, cmReal_t* logProbPtr )
  977. {
  978. bool scaleFl = cmIsFlag(flags,kLogScaleHmmFl);
  979. cmReal_t logProb = 0;
  980. cmReal_t* abp = alphaM; // define first dest. column
  981. const cmReal_t* aep = abp + p->stateN;
  982. const cmReal_t* sts = p->stsM + (obsV[0] * p->stateN); // stsM[] column for assoc'd with first obs. symbol
  983. unsigned i;
  984. // calc the prob of begining in each state given the obs. symbol
  985. for(i=0; abp < aep; ++i )
  986. *abp++ = *initPrV++ * *sts++;
  987. // scale to prevent underflow
  988. if( scaleFl )
  989. {
  990. cmReal_t sum = cmVOR_Sum(abp-p->stateN,p->stateN);
  991. if( sum > 0 )
  992. {
  993. cmVOR_DivVS( abp-p->stateN,p->stateN,sum);
  994. logProb += log(sum);
  995. }
  996. }
  997. // for each time step
  998. for(i=1; i<obsN; ++i)
  999. {
  1000. // next state 0 (first col, first row) is calc'd first
  1001. const cmReal_t* tm = p->transM;
  1002. // pick the stsM[] column assoc'd with ith observation symbol
  1003. const cmReal_t* sts = p->stsM + (obsV[i] * p->stateN);
  1004. // store a pointer to the alpha column assoc'd with obsV[i-1]
  1005. const cmReal_t* app0 = abp - p->stateN;
  1006. aep = abp + p->stateN;
  1007. // for each dest state
  1008. while( abp < aep )
  1009. {
  1010. // prob of being in each state on the previous time step
  1011. const cmReal_t* app = app0;
  1012. const cmReal_t* ape = app + p->stateN;
  1013. *abp = 0;
  1014. // for each src state - calc prob. of trans from src to dest
  1015. while( app<ape )
  1016. *abp += *app++ * *tm++;
  1017. // calc prob of obs symbol in dest state
  1018. *abp++ *= *sts++;
  1019. }
  1020. // scale to prevent underflow
  1021. if( scaleFl )
  1022. {
  1023. cmReal_t sum = cmVOR_Sum(abp-p->stateN,p->stateN);
  1024. if( sum > 0 )
  1025. {
  1026. cmVOR_DivVS( abp-p->stateN,p->stateN,sum);
  1027. logProb += log(sum);
  1028. }
  1029. }
  1030. }
  1031. if( logProbPtr != NULL )
  1032. *logProbPtr = logProb;
  1033. return cmOkRC;
  1034. }
  1035. cmRC_t cmDHmmBcmkwardEval( cmDhmm* p, const unsigned* obsV, unsigned obsN, cmReal_t* betaM, unsigned flags )
  1036. {
  1037. bool scaleFl = cmIsFlag(flags,kLogScaleHmmFl);
  1038. int i,j,t;
  1039. cmVOR_Fill(betaM+((obsN-1)*p->stateN),p->stateN,1.0);
  1040. // for each time step
  1041. for(t=obsN-2; t>=0; --t)
  1042. {
  1043. // for each state at t
  1044. for(i=0; i<p->stateN; ++i)
  1045. {
  1046. double Bt = 0;
  1047. // for each state at t+1
  1048. for(j=0; j<p->stateN; ++j)
  1049. {
  1050. double aij = p->transM[ (j * p->stateN) + i ];
  1051. double bj = p->stsM[ (obsV[t+1] * p->stateN) + j ];
  1052. double Bt1 = betaM[ ((t+1) * p->stateN) + j ];
  1053. Bt += aij * bj * Bt1;
  1054. }
  1055. betaM[ (t * p->stateN) + i ] = Bt;
  1056. }
  1057. if( scaleFl )
  1058. {
  1059. double* bp = betaM + (t * p->stateN);
  1060. double sum = cmVOR_Sum(bp, p->stateN );
  1061. if( sum > 0 )
  1062. cmVOR_DivVS( bp, p->stateN, sum );
  1063. }
  1064. }
  1065. return cmOkRC;
  1066. }
  1067. void _cmDhmmNormRow( cmReal_t* p, unsigned pn, unsigned stride, const cmReal_t* sp )
  1068. {
  1069. if( sp == NULL )
  1070. sp = p;
  1071. cmReal_t sum = 0;
  1072. unsigned n = pn * stride;
  1073. const cmReal_t* bp = sp;
  1074. const cmReal_t* ep = bp + n;
  1075. for(; bp<ep; bp+=stride)
  1076. sum += *bp;
  1077. for(ep = p+n; p<ep; p+=stride,sp+=stride)
  1078. *p = *sp / sum;
  1079. }
  1080. void _cmDhmmNormMtxRows( cmReal_t* dp, unsigned rn, unsigned cn, const cmReal_t* sp )
  1081. {
  1082. const cmReal_t* erp = sp + rn;
  1083. while( sp < erp )
  1084. _cmDhmmNormRow( dp++, cn, rn, sp++ );
  1085. }
  1086. cmRC_t cmDhmmTrainEM( cmDhmm* p, const unsigned* obsV, unsigned obsN, unsigned iterCnt, unsigned flags )
  1087. {
  1088. unsigned i,j,k,t;
  1089. cmReal_t alphaM[ p->stateN * obsN ];
  1090. cmReal_t betaM[ p->stateN * obsN ];
  1091. cmReal_t g[ p->stateN * obsN ];
  1092. cmReal_t q[ p->stateN * p->symN ];
  1093. cmReal_t E[ p->stateN * p->stateN ];
  1094. cmReal_t logProb = 0;
  1095. //cmDhmmReport(p->obj.ctx,p);
  1096. for(k=0; k<iterCnt; ++k)
  1097. {
  1098. cmVOR_Fill( q, (p->stateN * p->symN), 0 );
  1099. cmVOR_Fill( E, (p->stateN * p->stateN), 0 );
  1100. // calculate alpha and beta
  1101. cmDHmmForwardEval( p, p->initV, obsV, obsN, alphaM, flags, &logProb);
  1102. cmDHmmBcmkwardEval( p, obsV, obsN, betaM, flags );
  1103. // gamma[ stateN, obsN ] = alphaM .* betaM - gamma is the probability of being in each state at each time step
  1104. cmVOR_MultVVV( g,(p->stateN*obsN), alphaM, betaM );
  1105. // normalize gamma
  1106. for(i=0; i<obsN; ++i)
  1107. cmVOR_NormalizeProbability( g + (i*p->stateN), p->stateN );
  1108. //printf("ITER:%i logProb:%f\n",k,logProb);
  1109. // count the number of times state i emits obsV[0] in the starting location
  1110. cmVOR_Copy( q + (obsV[0] * p->stateN), p->stateN, g );
  1111. for(t=0; t<obsN-1; ++t)
  1112. {
  1113. // point to alpha[:,t] and beta[:,t+1]
  1114. const cmReal_t* alpha_t0 = alphaM + (t*p->stateN);
  1115. const cmReal_t* beta_t1 = betaM + ((t+1)*p->stateN);
  1116. cmReal_t Et[ p->stateN * p->stateN ];
  1117. cmReal_t Esum = 0;
  1118. // for each source state
  1119. for(i=0; i<p->stateN; ++i)
  1120. {
  1121. // for each dest state
  1122. for(j=0; j<p->stateN; ++j)
  1123. {
  1124. // prob of transitioning from state i to j and emitting obs[t] at time t
  1125. cmReal_t Eps = alpha_t0[i] * p->transM[ (j*p->stateN) + i ] * p->stsM[ (obsV[t+1]*p->stateN) + j ] * beta_t1[j];
  1126. // count the number of transitions from i to j
  1127. Et[ (j*p->stateN) + i ] = Eps;
  1128. Esum += Eps;
  1129. }
  1130. // count the number of times state i emits obsV[t]
  1131. q[ (obsV[t+1] * p->stateN) + i ] += g[ ((t+1)*p->stateN) + i ];
  1132. }
  1133. // normalize Et and sum it into E
  1134. cmVOR_DivVS( Et, (p->stateN*p->stateN), Esum );
  1135. cmVOR_AddVV( E, (p->stateN*p->stateN), Et );
  1136. }
  1137. // update the model
  1138. _cmDhmmNormMtxRows( p->initV, 1, p->stateN, g );
  1139. _cmDhmmNormMtxRows( p->transM, p->stateN, p->stateN, E );
  1140. _cmDhmmNormMtxRows( p->stsM, p->stateN, p->symN, q );
  1141. }
  1142. return cmOkRC;
  1143. }
  1144. cmRC_t cmDhmmReport( cmDhmm* p )
  1145. {
  1146. cmVOR_PrintL("initV:\n", p->obj.err.rpt, 1, p->stateN, p->initV );
  1147. cmVOR_PrintL("transM:\n", p->obj.err.rpt, p->stateN, p->stateN, p->transM );
  1148. cmVOR_PrintL("symM:\n", p->obj.err.rpt, p->stateN, p->symN, p->stsM );
  1149. return cmOkRC;
  1150. }
  1151. void cmDhmmTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  1152. {
  1153. unsigned stateN = 2;
  1154. unsigned symN = 3;
  1155. unsigned obsN = 4;
  1156. unsigned iterN = 10;
  1157. cmReal_t initV0[ stateN ];
  1158. cmReal_t transM0[ stateN * stateN ];
  1159. cmReal_t stsM0[ symN * stateN ];
  1160. cmReal_t initV1[ stateN ];
  1161. cmReal_t transM1[ stateN * stateN ];
  1162. cmReal_t stsM1[ symN * stateN ];
  1163. unsigned obsV[ obsN ];
  1164. unsigned hist[ symN ];
  1165. unsigned genFl = kManualProbHmmFl;
  1166. cmReal_t initV[] =
  1167. {
  1168. 0.44094,
  1169. 0.55906
  1170. };
  1171. cmReal_t transM[] =
  1172. {
  1173. 0.48336,
  1174. 0.81353,
  1175. 0.51664,
  1176. 0.18647,
  1177. };
  1178. cmReal_t stsM[] =
  1179. {
  1180. 0.20784,
  1181. 0.18698,
  1182. 0.43437,
  1183. 0.24102,
  1184. 0.35779,
  1185. 0.57199
  1186. };
  1187. unsigned obsM[] = { 2, 2, 2, 0 };
  1188. cmReal_t initV2[] = { 0.79060, 0.20940 };
  1189. cmReal_t transM2[] = { 0.508841, 0.011438, 0.491159, 0.988562 };
  1190. cmReal_t stsM2[] = { 0.25789, 0.35825, 0.61981, 0.42207, 0.12230, 0.21969 };
  1191. //srand( time(NULL) );
  1192. // generate a random HMM
  1193. _cmDhmmGenProb( initV0, 1, stateN, genFl, initV );
  1194. _cmDhmmGenProb( transM0, stateN, stateN, genFl, transM );
  1195. _cmDhmmGenProb( stsM0, stateN, symN, genFl, stsM );
  1196. cmCtx* c = cmCtxAlloc( NULL, rpt, lhH, stH);
  1197. cmDhmm* h0p = cmDhmmAlloc( c, NULL, stateN, symN, initV0, transM0, stsM0 );
  1198. // generate an observation sequence based on the random HMM
  1199. //cmDhmmGenObsSequence(c, h0p, obsV, obsN );
  1200. memcpy(obsV,obsM,obsN*sizeof(unsigned));
  1201. if( 0 )
  1202. {
  1203. // print the HMM
  1204. cmDhmmReport( h0p);
  1205. // print the observation symbols
  1206. cmVOU_PrintL("obs:\n", rpt, 1, obsN, obsV );
  1207. // print the histogram of the obs. symbols
  1208. cmVOU_Hist( hist, symN, obsV, obsN );
  1209. cmVOU_PrintL("hist:\n", rpt, 1, symN, hist );
  1210. // calc alpha (the forward probabilities)
  1211. cmReal_t alphaM[ h0p->stateN*obsN ];
  1212. cmReal_t logProb=0;
  1213. cmDHmmForwardEval( h0p, h0p->initV, obsV, obsN, alphaM, kLogScaleHmmFl, &logProb);
  1214. printf("log prob:%f\n alpha:\n", logProb );
  1215. cmVOR_Print( rpt, h0p->stateN, obsN, alphaM );
  1216. // calc beta (the bcmkward probabilities)
  1217. cmReal_t betaM[ h0p->stateN*obsN ];
  1218. logProb=0;
  1219. cmDHmmBcmkwardEval( h0p, obsV, obsN, betaM, kLogScaleHmmFl);
  1220. printf("log prob:%f\n beta:\n", logProb );
  1221. cmVOR_Print( h0p->obj.err.rpt, h0p->stateN, obsN, betaM );
  1222. }
  1223. // initialize a second HMM with random probabilities
  1224. _cmDhmmGenProb( initV1, 1, stateN, kManualProbHmmFl, initV2 );
  1225. _cmDhmmGenProb( transM1, stateN, stateN, kManualProbHmmFl, transM2 );
  1226. _cmDhmmGenProb( stsM1, stateN, symN, kManualProbHmmFl, stsM2 );
  1227. cmDhmm* h1p = cmDhmmAlloc( c, NULL, stateN, symN, initV1, transM1, stsM1 );
  1228. cmDhmmTrainEM( h1p, obsV, obsN, iterN, kLogScaleHmmFl );
  1229. cmDhmmFree(&h1p);
  1230. cmDhmmFree(&h0p);
  1231. cmCtxFree(&c);
  1232. }
  1233. //------------------------------------------------------------------------------------------------------------
  1234. cmConvolve* cmConvolveAlloc( cmCtx* c, cmConvolve* ap, const cmSample_t* h, unsigned hn, unsigned procSmpCnt )
  1235. {
  1236. cmConvolve* p = cmObjAlloc( cmConvolve, c, ap);
  1237. p->fft = cmFftAllocSR( c,NULL,NULL,0,kNoConvertFftFl);
  1238. p->ifft= cmIFftAllocRS(c,NULL,p->fft->binCnt);
  1239. if( hn > 0 && procSmpCnt > 0 )
  1240. if( cmConvolveInit(p,h,hn,procSmpCnt) != cmOkRC )
  1241. cmObjFree(&p);
  1242. return p;
  1243. }
  1244. cmRC_t cmConvolveFree( cmConvolve** pp )
  1245. {
  1246. cmRC_t rc;
  1247. cmConvolve* p = *pp;
  1248. if( pp == NULL || *pp == NULL )
  1249. return cmOkRC;
  1250. if((rc = cmConvolveFinal(p)) != cmOkRC )
  1251. return cmOkRC;
  1252. cmFftFreeSR(&p->fft);
  1253. cmIFftFreeRS(&p->ifft);
  1254. cmMemPtrFree(&p->H);
  1255. cmMemPtrFree(&p->outV);
  1256. cmObjFree(pp);
  1257. return cmOkRC;
  1258. }
  1259. cmRC_t cmConvolveInit( cmConvolve* p, const cmSample_t* h, unsigned hn, unsigned procSmpCnt )
  1260. {
  1261. cmRC_t rc;
  1262. unsigned i;
  1263. unsigned cn = cmNextPowerOfTwo( hn + procSmpCnt - 1 );
  1264. if((rc = cmConvolveFinal(p)) != cmOkRC )
  1265. return rc;
  1266. cmFftInitSR( p->fft, NULL, cn, kNoConvertFftFl );
  1267. cmIFftInitRS( p->ifft, p->fft->binCnt);
  1268. p->H = cmMemResizeZ( cmComplexR_t,p->H, p->fft->binCnt );
  1269. p->outV = cmMemResizeZ( cmSample_t,p->outV, cn );
  1270. p->olaV = p->outV + procSmpCnt;
  1271. p->outN = procSmpCnt;
  1272. p->hn = hn;
  1273. // take the FFT of the impulse response
  1274. cmFftExecSR( p->fft, h, hn );
  1275. // copy the FFT of the impulse response to p->H[]
  1276. for(i=0; i<p->fft->binCnt; ++i)
  1277. p->H[i] = p->fft->complexV[i] / p->fft->wndSmpCnt;
  1278. return cmOkRC;
  1279. }
  1280. cmRC_t cmConvolveFinal( cmConvolve* p )
  1281. { return cmOkRC; }
  1282. cmRC_t cmConvolveExec( cmConvolve* p, const cmSample_t* x, unsigned xn )
  1283. {
  1284. unsigned i;
  1285. // take FT of input signal
  1286. cmFftExecSR( p->fft, x, xn );
  1287. // multiply the signal spectra of the input signal and impulse response
  1288. for(i=0; i<p->fft->binCnt; ++i)
  1289. p->ifft->complexV[i] = p->H[i] * p->fft->complexV[i];
  1290. // take the IFFT of the convolved spectrum
  1291. cmIFftExecRS(p->ifft,NULL);
  1292. // sum with previous impulse response tail
  1293. cmVOS_AddVVV( p->outV, p->outN-1, p->olaV, p->ifft->outV );
  1294. // first sample of the impulse response tail is complete
  1295. p->outV[p->outN-1] = p->ifft->outV[p->outN-1];
  1296. // store the new impulse response tail
  1297. cmVOS_Copy(p->olaV,p->hn-1,p->ifft->outV + p->outN );
  1298. return cmOkRC;
  1299. }
  1300. cmRC_t cmConvolveSignal( cmCtx* c, const cmSample_t* h, unsigned hn, const cmSample_t* x, unsigned xn, cmSample_t* y, unsigned yn )
  1301. {
  1302. cmConvolve* p = cmConvolveAlloc(c,NULL,h,hn,xn);
  1303. cmConvolveExec(p,x,xn);
  1304. unsigned n = cmMin(p->outN,yn);
  1305. cmVOS_Copy(y,n,p->outV);
  1306. if( yn > p->outN )
  1307. {
  1308. unsigned m = cmMin(yn-p->outN,p->hn-1);
  1309. cmVOS_Copy(y+n,m,p->olaV);
  1310. }
  1311. cmConvolveFree(&p);
  1312. return cmOkRC;
  1313. }
  1314. cmRC_t cmConvolveTest(cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  1315. {
  1316. cmCtx *c = cmCtxAlloc(NULL,rpt,lhH,stH);
  1317. cmSample_t h[] = { 1, .5, .25, 0, 0 };
  1318. unsigned hn = sizeof(h) / sizeof(h[0]);
  1319. cmSample_t x[] = { 1, 0, 0, 0, 1, 0, 0, 0 };
  1320. unsigned xn = sizeof(x) / sizeof(x[0]);
  1321. unsigned yn = xn+hn-1;
  1322. cmSample_t y[yn];
  1323. //cmVOS_Hann(h,5);
  1324. cmConvolve* p = cmConvolveAlloc(c,NULL,h,hn,xn);
  1325. cmConvolveExec(p,x,xn);
  1326. cmVOS_Print( rpt, 1, p->outN, p->outV );
  1327. cmVOS_Print( rpt, 1, p->hn-1, p->olaV );
  1328. cmConvolveFree(&p);
  1329. cmConvolveSignal(c,h,hn,x,xn,y,yn);
  1330. cmVOS_Print( rpt, 1, hn+xn-1, y );
  1331. cmCtxFree(&c);
  1332. return cmOkRC;
  1333. }
  1334. //------------------------------------------------------------------------------------------------------------
  1335. cmBfcc* cmBfccAlloc( cmCtx* ctx, cmBfcc* ap, unsigned bandCnt, unsigned binCnt, double binHz )
  1336. {
  1337. cmBfcc* p = cmObjAlloc( cmBfcc, ctx, ap );
  1338. if( bandCnt > 0 )
  1339. if( cmBfccInit( p, bandCnt, binCnt, binHz ) != cmOkRC )
  1340. cmBfccFree(&p);
  1341. return p;
  1342. }
  1343. cmRC_t cmBfccFree( cmBfcc** pp )
  1344. {
  1345. cmRC_t rc;
  1346. if( pp== NULL || *pp==NULL)
  1347. return cmOkRC;
  1348. cmBfcc* p = *pp;
  1349. if((rc = cmBfccFinal(p)) != cmOkRC )
  1350. return rc;
  1351. cmMemPtrFree(&p->dctMtx);
  1352. cmMemPtrFree(&p->filtMask);
  1353. cmMemPtrFree(&p->outV);
  1354. cmObjFree(pp);
  1355. return rc;
  1356. }
  1357. cmRC_t cmBfccInit( cmBfcc* p, unsigned bandCnt, unsigned binCnt, double binHz )
  1358. {
  1359. cmRC_t rc;
  1360. if((rc = cmBfccFinal(p)) != cmOkRC )
  1361. return rc;
  1362. p->dctMtx = cmMemResizeZ( cmReal_t, p->dctMtx, bandCnt*bandCnt);
  1363. p->filtMask = cmMemResizeZ( cmReal_t, p->filtMask, bandCnt*binCnt);
  1364. p->outV = cmMemResizeZ( cmReal_t, p->outV, bandCnt );
  1365. p->binCnt = binCnt;
  1366. p->bandCnt = bandCnt;
  1367. cmVOR_BarkMask( p->filtMask, bandCnt, binCnt, binHz );
  1368. cmVOR_DctMatrix(p->dctMtx, bandCnt, bandCnt );
  1369. return rc;
  1370. }
  1371. cmRC_t cmBfccFinal( cmBfcc* p )
  1372. { return cmOkRC; }
  1373. cmRC_t cmBfccExec( cmBfcc* p, const cmReal_t* magV, unsigned binCnt )
  1374. {
  1375. assert( binCnt <= p->binCnt );
  1376. cmReal_t t[ p->bandCnt ];
  1377. cmReal_t v[ binCnt ];
  1378. // convert magnitude to power
  1379. cmVOR_PowVVS(v,binCnt,magV,2.0);
  1380. // apply the filter mask to the power spectrum
  1381. cmVOR_MultVMV( t, p->bandCnt, p->filtMask, binCnt, v );
  1382. //cmVOR_PrintL("\t:\n", p->obj.ctx->outFuncPtr, 1, p->bandCnt, t);
  1383. cmVOR_ReplaceLte( t, p->bandCnt, t, 0, 0.1e-5 );
  1384. cmVOR_LogV( t, p->bandCnt, t );
  1385. // decorellate the bands with a DCT
  1386. cmVOR_MultVMV( p->outV, p->bandCnt, p->dctMtx, p->bandCnt, t );
  1387. return cmOkRC;
  1388. }
  1389. void cmBfccTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  1390. {
  1391. double srate = 11025;
  1392. unsigned binCnt = 129;
  1393. double binHz = srate/(binCnt-1);
  1394. unsigned bandCnt = kDefaultBarkBandCnt;
  1395. cmCtx* c = cmCtxAlloc( NULL, rpt, lhH, stH );
  1396. cmBfcc* b = cmBfccAlloc( c, NULL, bandCnt, binCnt, binHz );
  1397. cmReal_t powV[] = {
  1398. 0.8402, 0.3944, 0.7831, 0.7984, 0.9116, 0.1976, 0.3352, 0.7682, 0.2778, 0.5540,
  1399. 0.4774, 0.6289, 0.3648, 0.5134, 0.9522, 0.9162, 0.6357, 0.7173, 0.1416, 0.6070,
  1400. 0.0163, 0.2429, 0.1372, 0.8042, 0.1567, 0.4009, 0.1298, 0.1088, 0.9989, 0.2183,
  1401. 0.5129, 0.8391, 0.6126, 0.2960, 0.6376, 0.5243, 0.4936, 0.9728, 0.2925, 0.7714,
  1402. 0.5267, 0.7699, 0.4002, 0.8915, 0.2833, 0.3525, 0.8077, 0.9190, 0.0698, 0.9493,
  1403. 0.5260, 0.0861, 0.1922, 0.6632, 0.8902, 0.3489, 0.0642, 0.0200, 0.4577, 0.0631,
  1404. 0.2383, 0.9706, 0.9022, 0.8509, 0.2667, 0.5398, 0.3752, 0.7602, 0.5125, 0.6677,
  1405. 0.5316, 0.0393, 0.4376, 0.9318, 0.9308, 0.7210, 0.2843, 0.7385, 0.6400, 0.3540,
  1406. 0.6879, 0.1660, 0.4401, 0.8801, 0.8292, 0.3303, 0.2290, 0.8934, 0.3504, 0.6867,
  1407. 0.9565, 0.5886, 0.6573, 0.8587, 0.4396, 0.9240, 0.3984, 0.8148, 0.6842, 0.9110,
  1408. 0.4825, 0.2158, 0.9503, 0.9201, 0.1477, 0.8811, 0.6411, 0.4320, 0.6196, 0.2811,
  1409. 0.7860, 0.3075, 0.4470, 0.2261, 0.1875, 0.2762, 0.5564, 0.4165, 0.1696, 0.9068,
  1410. 0.1032, 0.1261, 0.4954, 0.7605, 0.9848, 0.9350, 0.6844, 0.3832, 0.7498 };
  1411. //cmVOR_Random(powV, binCnt, 0.0, 1.0 );
  1412. cmBfccExec(b,powV,binCnt);
  1413. //cmVOR_PrintL("\nin:\n", rpt, 1, binCnt, powV);
  1414. //cmVOR_PrintL("\nfilt:\n", rpt, bandCnt, binCnt, b->filtMask);
  1415. //cmVOR_PrintL("\ndct:\n", rpt, bandCnt, bandCnt,b->dctMtx);
  1416. cmVOR_PrintL("\nbfcc:\n", rpt, 1, bandCnt, b->outV);
  1417. cmBfccFree(&b);
  1418. cmCtxFree(&c);
  1419. }
  1420. //------------------------------------------------------------------------------------------------------------
  1421. cmCeps* cmCepsAlloc( cmCtx* ctx, cmCeps* ap, unsigned binCnt, unsigned outN )
  1422. {
  1423. cmCeps* p = cmObjAlloc( cmCeps, ctx, ap );
  1424. //cmIFftAllocRR( ctx, &p->ft, 0 );
  1425. if( binCnt > 0 )
  1426. if( cmCepsInit( p, binCnt, outN ) != cmOkRC )
  1427. cmCepsFree(&p);
  1428. return p;
  1429. }
  1430. cmRC_t cmCepsFree( cmCeps** pp )
  1431. {
  1432. cmRC_t rc;
  1433. if( pp== NULL || *pp==NULL)
  1434. return cmOkRC;
  1435. cmCeps* p = *pp;
  1436. if((rc = cmCepsFinal(p)) != cmOkRC )
  1437. return rc;
  1438. //cmObjFreeStatic( cmIFftFreeRR, cmIFftRR, p->ft );
  1439. cmMemPtrFree(&p->dctM);
  1440. cmMemPtrFree(&p->outV);
  1441. cmObjFree(pp);
  1442. return rc;
  1443. }
  1444. cmRC_t cmCepsInit( cmCeps* p, unsigned binCnt, unsigned outN )
  1445. {
  1446. cmRC_t rc;
  1447. if((rc = cmCepsFinal(p)) != cmOkRC )
  1448. return rc;
  1449. //cmIFftInitRR( &p->ft, binCnt );
  1450. p->dct_cn = (binCnt-1)*2;
  1451. p->dctM = cmMemResize( cmReal_t, p->dctM, outN*p->dct_cn );
  1452. p->outN = outN; //p->ft.outN;
  1453. p->outV = cmMemResizeZ( cmReal_t, p->outV, outN ); //p->ft.outV;
  1454. p->binCnt = binCnt;
  1455. assert( outN <= p->dct_cn );
  1456. cmVOR_DctMatrix( p->dctM, outN, p->dct_cn );
  1457. return rc;
  1458. }
  1459. cmRC_t cmCepsFinal( cmCeps* p )
  1460. { return cmOkRC; }
  1461. cmRC_t cmCepsExec( cmCeps* p, const cmReal_t* magV, const cmReal_t* phsV, unsigned binCnt )
  1462. {
  1463. assert( binCnt == p->binCnt );
  1464. cmReal_t v[ p->dct_cn ];
  1465. // guard against zeros in the magn spectrum
  1466. cmVOR_ReplaceLte(v,binCnt,magV,0.0,0.00001);
  1467. // take the log of the spectrum
  1468. cmVOR_LogV(v,binCnt,v);
  1469. // reconstruct the negative frequencies
  1470. int i,j;
  1471. for(i=1,j=p->dct_cn-1; i<binCnt; ++i,--j)
  1472. v[j] = v[i];
  1473. // take the DCT
  1474. cmVOR_MultVMV( p->outV, p->outN, p->dctM, p->dct_cn, v );
  1475. //cmIFftExecPolarRR( &p->ft, v, phsV );
  1476. return cmOkRC;
  1477. }
  1478. //------------------------------------------------------------------------------------------------------------
  1479. cmOla* cmOlaAlloc( cmCtx* ctx, cmOla* ap, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned procSmpCnt, unsigned wndTypeId )
  1480. {
  1481. cmOla* p = cmObjAlloc( cmOla, ctx, ap );
  1482. cmWndFuncAlloc( ctx, &p->wf, kHannWndId, wndSmpCnt, 0);
  1483. if( wndSmpCnt > 0 )
  1484. if( cmOlaInit(p,wndSmpCnt,hopSmpCnt,procSmpCnt,wndTypeId) != cmOkRC )
  1485. cmOlaFree(&p);
  1486. return p;
  1487. }
  1488. cmRC_t cmOlaFree( cmOla** pp )
  1489. {
  1490. cmRC_t rc;
  1491. if( pp==NULL || *pp==NULL )
  1492. return cmOkRC;
  1493. cmOla* p = *pp;
  1494. if(( rc = cmOlaFinal(p)) != cmOkRC )
  1495. return rc;
  1496. cmMemPtrFree(&p->bufV);
  1497. cmMemPtrFree(&p->outV);
  1498. cmObjFreeStatic( cmWndFuncFree, cmWndFunc, p->wf );
  1499. cmObjFree(pp);
  1500. return rc;
  1501. }
  1502. cmRC_t cmOlaInit( cmOla* p, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned procSmpCnt, unsigned wndTypeId )
  1503. {
  1504. cmRC_t rc;
  1505. if((rc = cmOlaFinal(p)) != cmOkRC )
  1506. return rc;
  1507. if((rc = cmWndFuncInit( &p->wf, wndTypeId, wndSmpCnt, 0)) != cmOkRC )
  1508. return rc;
  1509. p->bufV = cmMemResizeZ( cmSample_t, p->bufV, wndSmpCnt );
  1510. p->outV = cmMemResizeZ( cmSample_t, p->outV, hopSmpCnt );
  1511. p->outPtr = p->outV + hopSmpCnt;
  1512. // hopSmpCnt must be an even multiple of procSmpCnt
  1513. assert( hopSmpCnt % procSmpCnt == 0 );
  1514. assert( wndSmpCnt >= hopSmpCnt );
  1515. p->wndSmpCnt = wndSmpCnt;
  1516. p->hopSmpCnt = hopSmpCnt;
  1517. p->procSmpCnt= procSmpCnt;
  1518. p->idx = 0;
  1519. return rc;
  1520. }
  1521. cmRC_t cmOlaFinal( cmOla* p )
  1522. { return cmOkRC; }
  1523. // The incoming buffer and the ola buf (bufV)
  1524. // can be divided into three logical parts:
  1525. //
  1526. // [head][middle][tail]
  1527. //
  1528. // head = hopSmpCnt values
  1529. // tail = hopSmpCnt values
  1530. // middle = wndSmpCnt - (2*hopSmpCnt) values
  1531. //
  1532. // Each exec can be broken into three phases:
  1533. //
  1534. // outV = bufV[tail] + in[head]
  1535. // bufV[middle] += in[middle]
  1536. // bufV[tail] = in[tail]
  1537. //
  1538. cmRC_t cmOlaExecS( cmOla* p, const cmSample_t* sp, unsigned sN )
  1539. {
  1540. assert( sN == p->wndSmpCnt );
  1541. cmRC_t rc = cmOkRC;
  1542. const cmSample_t* ep = sp + sN;
  1543. const cmSample_t* wp = p->wf.wndV;
  1544. int i,j,k,n;
  1545. // [Sum head of incoming samples with tail of ola buf]
  1546. // fill outV with the bufV[idx:idx+hopSmpCnt] + sp[hopSmpCnt]
  1547. for(i=0; i<p->hopSmpCnt; ++i)
  1548. {
  1549. p->outV[i] = p->bufV[p->idx++] + (*sp++ * *wp++);
  1550. if( p->idx == p->wndSmpCnt )
  1551. p->idx = 0;
  1552. }
  1553. // [Sum middle of incoming samples with middle of ola buf]
  1554. // sum next wndSmpCnt - hopSmpCnt samples of sp[] into bufV[]
  1555. n = p->wndSmpCnt - (2*p->hopSmpCnt);
  1556. k = p->idx;
  1557. for(j=0; j<n; ++j)
  1558. {
  1559. p->bufV[k++] += (*sp++ * *wp++);
  1560. if( k == p->wndSmpCnt )
  1561. k = 0;
  1562. }
  1563. // [Assign tail of incoming to tail of ola buf]
  1564. // assign ending samples from sp[] into bufV[]
  1565. while( sp < ep )
  1566. {
  1567. p->bufV[k++] = (*sp++ * *wp++);
  1568. if( k == p->wndSmpCnt )
  1569. k = 0;
  1570. }
  1571. p->outPtr = p->outV;
  1572. return rc;
  1573. }
  1574. cmRC_t cmOlaExecR( cmOla* p, const cmReal_t* sp, unsigned sN )
  1575. {
  1576. assert( sN == p->wndSmpCnt );
  1577. cmRC_t rc = cmOkRC;
  1578. const cmReal_t* ep = sp + sN;
  1579. const cmSample_t* wp = p->wf.wndV;
  1580. int i,j,k,n;
  1581. // fill outV with the bufV[idx:idx+hopSmpCnt] + sp[hopSmpCnt]
  1582. for(i=0; i<p->hopSmpCnt; ++i)
  1583. {
  1584. p->outV[i] = p->bufV[p->idx++] + (*sp++ * *wp++);
  1585. if( p->idx == p->wndSmpCnt )
  1586. p->idx = 0;
  1587. }
  1588. // sum next wndSmpCnt - hopSmpCnt samples of sp[] into bufV[]
  1589. n = p->wndSmpCnt - (2*p->hopSmpCnt);
  1590. k = p->idx;
  1591. for(j=0; j<n; ++j)
  1592. {
  1593. p->bufV[k++] += (*sp++ * *wp++);
  1594. if( k == p->wndSmpCnt )
  1595. k = 0;
  1596. }
  1597. // assign ending samples from sp[] into bufV[]
  1598. while( sp < ep )
  1599. {
  1600. p->bufV[k++] = (*sp++ * *wp++);
  1601. if( k == p->wndSmpCnt )
  1602. k = 0;
  1603. }
  1604. p->outPtr = p->outV;
  1605. return rc;
  1606. }
  1607. const cmSample_t* cmOlaExecOut(cmOla* p)
  1608. {
  1609. const cmSample_t* sp = p->outPtr;
  1610. if( sp >= p->outV + p->hopSmpCnt )
  1611. return NULL;
  1612. p->outPtr += p->procSmpCnt;
  1613. return sp;
  1614. }
  1615. //------------------------------------------------------------------------------------------------------------
  1616. cmPhsToFrq* cmPhsToFrqAlloc( cmCtx* c, cmPhsToFrq* ap, double srate, unsigned binCnt, unsigned hopSmpCnt )
  1617. {
  1618. cmPhsToFrq* p = cmObjAlloc( cmPhsToFrq, c, ap );
  1619. if( srate != 0 )
  1620. if( cmPhsToFrqInit( p, srate, binCnt, hopSmpCnt ) != cmOkRC )
  1621. cmPhsToFrqFree(&p);
  1622. return p;
  1623. }
  1624. cmRC_t cmPhsToFrqFree( cmPhsToFrq** pp )
  1625. {
  1626. cmRC_t rc = cmOkRC;
  1627. cmPhsToFrq* p = *pp;
  1628. if( pp==NULL || *pp== NULL )
  1629. return rc;
  1630. if((rc = cmPhsToFrqFinal(p)) != cmOkRC )
  1631. return rc;
  1632. cmMemPtrFree(&p->hzV);
  1633. cmMemPtrFree(&p->phsV);
  1634. cmMemPtrFree(&p->wV);
  1635. cmObjFree(pp);
  1636. return rc;
  1637. }
  1638. cmRC_t cmPhsToFrqInit( cmPhsToFrq* p, double srate, unsigned binCnt, unsigned hopSmpCnt )
  1639. {
  1640. cmRC_t rc;
  1641. unsigned i;
  1642. if((rc = cmPhsToFrqFinal(p)) != cmOkRC )
  1643. return rc;
  1644. p->hzV = cmMemResizeZ( cmReal_t, p->hzV, binCnt );
  1645. p->phsV = cmMemResizeZ( cmReal_t, p->phsV, binCnt );
  1646. p->wV = cmMemResizeZ( cmReal_t, p->wV, binCnt );
  1647. p->srate = srate;
  1648. p->binCnt = binCnt;
  1649. p->hopSmpCnt = hopSmpCnt;
  1650. for(i=0; i<binCnt; ++i)
  1651. p->wV[i] = M_PI * i * hopSmpCnt / (binCnt-1);
  1652. return rc;
  1653. }
  1654. cmRC_t cmPhsToFrqFinal(cmPhsToFrq* p )
  1655. { return cmOkRC; }
  1656. cmRC_t cmPhsToFrqExec( cmPhsToFrq* p, const cmReal_t* phsV )
  1657. {
  1658. cmRC_t rc = cmOkRC;
  1659. unsigned i;
  1660. double twoPi = 2.0 * M_PI;
  1661. double den = twoPi * p->hopSmpCnt;
  1662. for(i=0; i<p->binCnt; ++i)
  1663. {
  1664. cmReal_t dPhs = phsV[i] - p->phsV[i];
  1665. // unwrap phase - see phase_study.m for explanation
  1666. cmReal_t k = round( (p->wV[i] - dPhs) / twoPi);
  1667. // convert phase change to Hz
  1668. p->hzV[i] = (k * twoPi + dPhs) * p->srate / den;
  1669. // store phase for next iteration
  1670. p->phsV[i] = phsV[i];
  1671. }
  1672. return rc;
  1673. }
  1674. //------------------------------------------------------------------------------------------------------------
  1675. cmPvAnl* cmPvAnlAlloc( cmCtx* ctx, cmPvAnl* ap, unsigned procSmpCnt, double srate, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned flags )
  1676. {
  1677. cmRC_t rc;
  1678. cmPvAnl* p = cmObjAlloc( cmPvAnl, ctx, ap );
  1679. cmShiftBufAlloc(ctx, &p->sb, procSmpCnt, wndSmpCnt, hopSmpCnt );
  1680. cmWndFuncAlloc( ctx, &p->wf, kHannWndId, wndSmpCnt, 0);
  1681. cmFftAllocSR( ctx, &p->ft, p->wf.outV, wndSmpCnt, kToPolarFftFl);
  1682. cmPhsToFrqAlloc(ctx, &p->pf, srate, p->ft.binCnt, hopSmpCnt );
  1683. if( procSmpCnt > 0 )
  1684. if((rc = cmPvAnlInit(p,procSmpCnt,srate,wndSmpCnt,hopSmpCnt,flags)) != cmOkRC )
  1685. cmPvAnlFree(&p);
  1686. return p;
  1687. }
  1688. cmRC_t cmPvAnlFree( cmPvAnl** pp )
  1689. {
  1690. cmRC_t rc;
  1691. if( pp==NULL || *pp==NULL )
  1692. return cmOkRC;
  1693. cmPvAnl* p = *pp;
  1694. if((rc = cmPvAnlFinal(p) ) != cmOkRC )
  1695. return rc;
  1696. cmObjFreeStatic( cmPhsToFrqFree, cmPhsToFrq, p->pf );
  1697. cmObjFreeStatic( cmFftFreeSR, cmFftSR, p->ft );
  1698. cmObjFreeStatic( cmWndFuncFree, cmWndFunc, p->wf );
  1699. cmObjFreeStatic( cmShiftBufFree, cmShiftBuf, p->sb );
  1700. cmObjFree(pp);
  1701. return rc;
  1702. }
  1703. cmRC_t cmPvAnlInit( cmPvAnl* p, unsigned procSmpCnt, double srate, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned flags )
  1704. {
  1705. cmRC_t rc;
  1706. if((rc = cmPvAnlFinal(p)) != cmOkRC )
  1707. return rc;
  1708. if((rc = cmShiftBufInit( &p->sb, procSmpCnt, wndSmpCnt, hopSmpCnt )) != cmOkRC )
  1709. return rc;
  1710. if((rc = cmWndFuncInit( &p->wf, kHannWndId | kNormByLengthWndFl, wndSmpCnt, 0)) != cmOkRC )
  1711. return rc;
  1712. if((rc = cmFftInitSR( &p->ft, p->wf.outV, wndSmpCnt, kToPolarFftFl)) != cmOkRC )
  1713. return rc;
  1714. if((rc = cmPhsToFrqInit( &p->pf, srate, p->ft.binCnt, hopSmpCnt)) != cmOkRC )
  1715. return rc;
  1716. // if the window was just initialized
  1717. // divide the window to indirectly apply the magnitude normalization
  1718. //if( p->wndSmpCnt != wndSmpCnt )
  1719. // cmVOS_DivVS( p->wf.wndV, p->wf.outN, wndSmpCnt );
  1720. p->flags = flags;
  1721. p->procSmpCnt = procSmpCnt;
  1722. p->wndSmpCnt = wndSmpCnt;
  1723. p->hopSmpCnt = hopSmpCnt;
  1724. p->binCnt = p->ft.binCnt;
  1725. p->magV = p->ft.magV;
  1726. p->phsV = p->ft.phsV;
  1727. p->hzV = p->pf.hzV;
  1728. return rc;
  1729. }
  1730. cmRC_t cmPvAnlFinal(cmPvAnl* p )
  1731. { return cmOkRC; }
  1732. bool cmPvAnlExec( cmPvAnl* p, const cmSample_t* x, unsigned xN )
  1733. {
  1734. bool fl = false;
  1735. while( cmShiftBufExec(&p->sb,x,xN) )
  1736. {
  1737. cmWndFuncExec(&p->wf, p->sb.outV, p->sb.wndSmpCnt );
  1738. cmFftExecSR(&p->ft,NULL,0);
  1739. if( cmIsFlag(p->flags,kCalcHzPvaFl) )
  1740. cmPhsToFrqExec(&p->pf,p->phsV);
  1741. fl = true;
  1742. }
  1743. return fl;
  1744. }
  1745. //------------------------------------------------------------------------------------------------------------
  1746. cmPvSyn* cmPvSynAlloc( cmCtx* ctx, cmPvSyn* ap, unsigned procSmpCnt, double outSrate, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned wndTypeId )
  1747. {
  1748. cmRC_t rc;
  1749. cmPvSyn* p = cmObjAlloc( cmPvSyn, ctx, ap );
  1750. cmWndFuncAlloc( ctx, &p->wf, kHannWndId, wndSmpCnt, 0);
  1751. cmIFftAllocRS( ctx, &p->ft, wndSmpCnt/2+1 );
  1752. cmOlaAlloc( ctx, &p->ola, wndSmpCnt, hopSmpCnt, procSmpCnt, wndTypeId );
  1753. if( procSmpCnt )
  1754. if((rc = cmPvSynInit(p,procSmpCnt,outSrate,wndSmpCnt,hopSmpCnt,wndTypeId)) != cmOkRC )
  1755. cmPvSynFree(&p);
  1756. return p;
  1757. }
  1758. cmRC_t cmPvSynFree( cmPvSyn** pp )
  1759. {
  1760. cmRC_t rc;
  1761. if( pp==NULL || *pp==NULL )
  1762. return cmOkRC;
  1763. cmPvSyn* p = *pp;
  1764. if((rc = cmPvSynFinal(p)) != cmOkRC )
  1765. return rc;
  1766. cmMemPtrFree(&p->minRphV);
  1767. cmMemPtrFree(&p->maxRphV);
  1768. cmMemPtrFree(&p->itrV);
  1769. cmMemPtrFree(&p->phs0V);
  1770. cmMemPtrFree(&p->phsV);
  1771. cmMemPtrFree(&p->mag0V);
  1772. cmMemPtrFree(&p->magV);
  1773. cmObjFreeStatic( cmOlaFree, cmOla, p->ola);
  1774. cmObjFreeStatic( cmIFftFreeRS, cmIFftRS, p->ft );
  1775. cmObjFreeStatic( cmWndFuncFree, cmWndFunc, p->wf );
  1776. cmObjFree(pp);
  1777. return cmOkRC;
  1778. }
  1779. cmRC_t cmPvSynInit( cmPvSyn* p, unsigned procSmpCnt, double outSrate, unsigned wndSmpCnt, unsigned hopSmpCnt, unsigned wndTypeId )
  1780. {
  1781. cmRC_t rc;
  1782. int k;
  1783. double twoPi = 2.0 * M_PI;
  1784. bool useHannFl = true;
  1785. int m = useHannFl ? 2 : 1;
  1786. if((rc = cmPvSynFinal(p)) != cmOkRC )
  1787. return rc;
  1788. p->outSrate = outSrate;
  1789. p->procSmpCnt = procSmpCnt;
  1790. p->wndSmpCnt = wndSmpCnt;
  1791. p->hopSmpCnt = hopSmpCnt;
  1792. p->binCnt = wndSmpCnt / 2 + 1;
  1793. p->minRphV = cmMemResizeZ( cmReal_t, p->minRphV, p->binCnt );
  1794. p->maxRphV = cmMemResizeZ( cmReal_t, p->maxRphV, p->binCnt );
  1795. p->itrV = cmMemResizeZ( cmReal_t, p->itrV, p->binCnt );
  1796. p->phs0V = cmMemResizeZ( cmReal_t, p->phs0V, p->binCnt );
  1797. p->phsV = cmMemResizeZ( cmReal_t, p->phsV, p->binCnt );
  1798. p->mag0V = cmMemResizeZ( cmReal_t, p->mag0V, p->binCnt );
  1799. p->magV = cmMemResizeZ( cmReal_t, p->magV, p->binCnt );
  1800. if((rc = cmWndFuncInit( &p->wf, wndTypeId, wndSmpCnt, 0)) != cmOkRC )
  1801. return rc;
  1802. if((rc = cmIFftInitRS( &p->ft, p->binCnt )) != cmOkRC )
  1803. return rc;
  1804. if((rc = cmOlaInit( &p->ola, wndSmpCnt, hopSmpCnt, procSmpCnt, wndTypeId )) != cmOkRC )
  1805. return rc;
  1806. for(k=0; k<p->binCnt; ++k)
  1807. {
  1808. // complete revolutions per hop in radians
  1809. p->itrV[k] = twoPi * floor((double)k * hopSmpCnt / wndSmpCnt );
  1810. p->minRphV[k] = ((cmReal_t)(k-m)) * hopSmpCnt * twoPi / wndSmpCnt;
  1811. p->maxRphV[k] = ((cmReal_t)(k+m)) * hopSmpCnt * twoPi / wndSmpCnt;
  1812. //printf("%f %f %f\n",p->itrV[k],p->minRphV[k],p->maxRphV[k]);
  1813. }
  1814. return rc;
  1815. }
  1816. cmRC_t cmPvSynFinal(cmPvSyn* p )
  1817. { return cmOkRC; }
  1818. cmRC_t cmPvSynExec( cmPvSyn* p, const cmReal_t* magV, const cmReal_t* phsV )
  1819. {
  1820. double twoPi = 2.0 * M_PI;
  1821. unsigned k;
  1822. for(k=0; k<p->binCnt; ++k)
  1823. {
  1824. // phase dist between cur and prv frame
  1825. cmReal_t dp = phsV[k] - p->phs0V[k];
  1826. // dist must be positive (accum phase always increases)
  1827. if( dp < -0.00001 )
  1828. dp += twoPi;
  1829. // add in complete revolutions based on the bin frequency
  1830. // (these would have been lost from 'dp' due to phase wrap)
  1831. dp += p->itrV[k];
  1832. // constrain the phase change to lie within the range of the kth bin
  1833. if( dp < p->minRphV[k] )
  1834. dp += twoPi;
  1835. if( dp > p->maxRphV[k] )
  1836. dp -= twoPi;
  1837. p->phsV[k] = p->phs0V[k] + dp;
  1838. p->magV[k] = p->mag0V[k];
  1839. p->phs0V[k] = phsV[k];
  1840. p->mag0V[k] = magV[k];
  1841. }
  1842. cmIFftExecPolarRS( &p->ft, magV, phsV );
  1843. cmOlaExecS( &p->ola, p->ft.outV, p->ft.outN );
  1844. //printf("%i %i\n",p->binCnt,p->ft.binCnt );
  1845. //cmVOR_Print( p->obj.ctx->outFuncPtr, 1, p->binCnt, magV );
  1846. //cmVOR_Print( p->obj.ctx->outFuncPtr, 1, p->binCnt, p->phsV );
  1847. //cmVOS_Print( p->obj.ctx->outFuncPtr, 1, 10, p->ft.outV );
  1848. return cmOkRC;
  1849. }
  1850. cmRC_t cmPvSynDoIt( cmPvSyn* p, const cmSample_t* v )
  1851. {
  1852. cmOlaExecS( &p->ola, v, p->wndSmpCnt );
  1853. //printf("%f\n",cmVOS_RMS(s,p->wndSmpCnt,p->wndSmpCnt));
  1854. return cmOkRC;
  1855. }
  1856. const cmSample_t* cmPvSynExecOut(cmPvSyn* p )
  1857. { return cmOlaExecOut(&p->ola); }
  1858. //------------------------------------------------------------------------------------------------------------
  1859. cmMidiSynth* cmMidiSynthAlloc( cmCtx* ctx, cmMidiSynth* ap, const cmMidiSynthPgm* pgmArray, unsigned pgmCnt, unsigned voiceCnt, unsigned procSmpCnt, unsigned outChCnt, cmReal_t srate )
  1860. {
  1861. cmMidiSynth* p = cmObjAlloc( cmMidiSynth, ctx, ap );
  1862. if( pgmArray != NULL )
  1863. if( cmMidiSynthInit( p, pgmArray, pgmCnt, voiceCnt, procSmpCnt, outChCnt, srate ) != cmOkRC )
  1864. cmMidiSynthFree(&p);
  1865. return p;
  1866. }
  1867. cmRC_t cmMidiSynthFree( cmMidiSynth** pp )
  1868. {
  1869. cmRC_t rc;
  1870. if( pp==NULL || *pp==NULL)
  1871. return cmOkRC;
  1872. cmMidiSynth* p = *pp;
  1873. if((rc = cmMidiSynthFinal(p)) != cmOkRC )
  1874. return rc;
  1875. cmMemPtrFree(&p->voiceArray);
  1876. cmMemPtrFree(&p->outM);
  1877. cmMemPtrFree(&p->outChArray);
  1878. cmObjFree(pp);
  1879. return cmOkRC;
  1880. }
  1881. cmRC_t cmMidiSynthInit( cmMidiSynth* p, const cmMidiSynthPgm* pgmArray, unsigned pgmCnt, unsigned voiceCnt, unsigned procSmpCnt, unsigned outChCnt, cmReal_t srate )
  1882. {
  1883. // at least one pgm must be given
  1884. assert( pgmCnt > 0 );
  1885. unsigned i;
  1886. cmRC_t rc;
  1887. if((rc = cmMidiSynthFinal(p)) != cmOkRC )
  1888. return rc;
  1889. p->voiceArray = cmMemResizeZ( cmMidiVoice, p->voiceArray, voiceCnt );
  1890. p->outM = cmMemResizeZ( cmSample_t, p->outM, outChCnt * procSmpCnt );
  1891. p->outChArray = cmMemResizeZ( cmSample_t*, p->outChArray, outChCnt );
  1892. p->avail = p->voiceArray;
  1893. p->voiceCnt = voiceCnt;
  1894. p->activeVoiceCnt = 0;
  1895. p->voiceStealCnt = 0;
  1896. p->procSmpCnt = procSmpCnt;
  1897. p->outChCnt = outChCnt;
  1898. p->srate = srate;
  1899. for(i=0; i<outChCnt; ++i)
  1900. p->outChArray[i] = p->outM + (i*procSmpCnt);
  1901. for(i=0; i<kMidiChCnt; ++i)
  1902. {
  1903. p->chArray[i].pgm = 0;
  1904. p->chArray[i].active = NULL;
  1905. p->chArray[i].pitchBend = 0;
  1906. p->chArray[i].synthPtr = p;
  1907. memset(p->chArray[i].midiCtl, 0, kMidiCtlCnt * sizeof(cmMidiByte_t));
  1908. }
  1909. for(i=0; i<voiceCnt; ++i)
  1910. {
  1911. p->voiceArray[i].index = i;
  1912. p->voiceArray[i].flags = 0;
  1913. p->voiceArray[i].pitch = kInvalidMidiPitch;
  1914. p->voiceArray[i].velocity = kInvalidMidiVelocity;
  1915. p->voiceArray[i].pgm.pgm = kInvalidMidiPgm;
  1916. p->voiceArray[i].pgm.cbPtr = NULL;
  1917. p->voiceArray[i].pgm.cbDataPtr = NULL;
  1918. p->voiceArray[i].chPtr = NULL;
  1919. p->voiceArray[i].link = i<voiceCnt-1 ? p->voiceArray + i + 1 : NULL;
  1920. }
  1921. for(i=0; i<pgmCnt; ++i)
  1922. {
  1923. unsigned idx = pgmArray[i].pgm;
  1924. if( idx >= kMidiPgmCnt )
  1925. rc = cmCtxRtCondition( &p->obj, cmArgAssertRC, "MIDI program change values must be less than %i.",kMidiPgmCnt);
  1926. else
  1927. {
  1928. p->pgmArray[ idx ].cbPtr = pgmArray[i].cbPtr;
  1929. p->pgmArray[ idx ].cbDataPtr = pgmArray[i].cbDataPtr;
  1930. p->pgmArray[ idx ].pgm = idx;
  1931. }
  1932. }
  1933. return rc;
  1934. }
  1935. cmRC_t cmMidiSynthFinal( cmMidiSynth* p )
  1936. { return cmOkRC; }
  1937. cmRC_t _cmMidiSynthOnNoteOn( cmMidiSynth* p, cmMidiByte_t ch, cmMidiByte_t pitch, cmMidiByte_t vel )
  1938. {
  1939. assert( ch < kMidiChCnt );
  1940. if( p->activeVoiceCnt == p->voiceCnt )
  1941. {
  1942. ++p->voiceStealCnt;
  1943. return cmOkRC;
  1944. }
  1945. assert( p->avail != NULL );
  1946. cmMidiSynthCh* chPtr = p->chArray + ch;
  1947. cmMidiVoice* vp = p->avail;
  1948. ++p->activeVoiceCnt;
  1949. // update avail
  1950. p->avail = p->avail->link;
  1951. // update active
  1952. vp->flags |= kActiveMsFl | kKeyGateMsFl;
  1953. vp->pitch = pitch;
  1954. vp->velocity = vel;
  1955. vp->pgm = p->pgmArray[ chPtr->pgm ];
  1956. vp->chPtr = chPtr;
  1957. vp->link = chPtr->active;
  1958. chPtr->active = vp;
  1959. vp->pgm.cbPtr( vp, kAttackMsId, NULL, 0 );
  1960. return cmOkRC;
  1961. }
  1962. cmRC_t _cmMidiSynthOnNoteOff( cmMidiSynth* p, cmMidiByte_t ch, cmMidiByte_t pitch, cmMidiByte_t vel )
  1963. {
  1964. assert( ch < kMidiChCnt );
  1965. cmMidiSynthCh* cp = p->chArray + ch;
  1966. cmMidiVoice* vp = cp->active;
  1967. // find the voice for the given pitch
  1968. while( vp != NULL )
  1969. {
  1970. if( (vp->pitch == pitch) && (cmIsFlag(vp->flags,kKeyGateMsFl)==true) )
  1971. break;
  1972. vp = vp->link;
  1973. }
  1974. // if no voice had a key down on this pitch
  1975. if( vp == NULL )
  1976. {
  1977. return cmOkRC;
  1978. }
  1979. // mark the key as 'up'
  1980. vp->flags = cmClrFlag(vp->flags,kKeyGateMsFl);
  1981. // if the sustain pedal is up
  1982. if( cp->midiCtl[ kSustainCtlMdId ] == 0 )
  1983. vp->pgm.cbPtr( vp, kReleaseMsId, NULL, 0 );
  1984. return cmOkRC;
  1985. }
  1986. cmRC_t _cmMidiSynthOnCtl( cmMidiSynth* p, cmMidiByte_t ch, cmMidiByte_t ctlId, cmMidiByte_t ctlValue )
  1987. {
  1988. assert( ch < kMidiChCnt && ctlId < kMidiCtlCnt );
  1989. cmMidiSynthCh* cp = p->chArray + ch;
  1990. cp->midiCtl[ ctlId ] = ctlValue;
  1991. // if the sustain pedal is going up
  1992. if( ctlId == kSustainCtlMdId && ctlValue == 0 )
  1993. {
  1994. cmMidiVoice* vp = cp->active;
  1995. while(vp != NULL)
  1996. {
  1997. if( cmIsFlag(vp->flags,kKeyGateMsFl)==false )
  1998. vp->pgm.cbPtr(vp, kReleaseMsId, NULL, 0 );
  1999. vp = vp->link;
  2000. }
  2001. }
  2002. //printf("%i %i %f\n",ctlId,ctlValue,ctlValue/127.0);
  2003. return cmOkRC;
  2004. }
  2005. cmRC_t cmMidiSynthOnMidi( cmMidiSynth* p, const cmMidiPacket_t* pktArray, unsigned pktCnt )
  2006. {
  2007. unsigned i=0;
  2008. for(i=0; i<pktCnt; ++i)
  2009. if( pktArray[i].msgArray != NULL )
  2010. {
  2011. unsigned j;
  2012. for(j=0; j<pktArray[i].msgCnt; ++j)
  2013. {
  2014. const cmMidiMsg* mp = pktArray[i].msgArray + j;
  2015. cmMidiByte_t ch = mp->status & 0x0f;
  2016. cmMidiByte_t status = mp->status & 0xf0;
  2017. switch( status )
  2018. {
  2019. case kNoteOnMdId:
  2020. if( mp->d1 != 0 )
  2021. {
  2022. _cmMidiSynthOnNoteOn(p,ch,mp->d0,mp->d1);
  2023. break;
  2024. }
  2025. // fall through
  2026. case kNoteOffMdId:
  2027. _cmMidiSynthOnNoteOff(p,ch,mp->d0,mp->d1);
  2028. break;
  2029. case kPolyPresMdId:
  2030. break;
  2031. case kCtlMdId:
  2032. _cmMidiSynthOnCtl( p, ch, mp->d0, mp->d1 );
  2033. break;
  2034. case kPgmMdId:
  2035. break;
  2036. case kChPresMdId:
  2037. break;
  2038. case kPbendMdId:
  2039. break;
  2040. default:
  2041. printf("Unknown MIDI status:%i %i\n",(int)status,(int)mp->status);
  2042. break;
  2043. }
  2044. }
  2045. }
  2046. return cmOkRC;
  2047. }
  2048. cmRC_t cmMidiSynthExec( cmMidiSynth* p, cmSample_t* outChArray[], unsigned outChCnt )
  2049. {
  2050. unsigned i;
  2051. cmSample_t** chArray = outChArray == NULL ? p->outChArray : outChArray;
  2052. unsigned chCnt = outChArray == NULL ? p->outChCnt : outChCnt;
  2053. // FIX: make one active chain attached to cmMidiSynth rather than many
  2054. // active chains attached to each channel - this will avoid the extra
  2055. // iterations below.
  2056. // for each channel
  2057. for(i=0; i<kMidiChCnt; ++i)
  2058. {
  2059. cmMidiVoice* vp = p->chArray[i].active;
  2060. cmMidiVoice* prv = NULL;
  2061. // for each voice assigned to this channel
  2062. while(vp != NULL)
  2063. {
  2064. // tell the voice to perform its DSP function - returns 0 if the voice is no longer active
  2065. if( vp->pgm.cbPtr( vp, kDspMsId, chArray, chCnt ) )
  2066. {
  2067. prv = vp;
  2068. vp = vp->link;
  2069. }
  2070. else
  2071. {
  2072. cmMidiVoice* nvp = vp->link;
  2073. // remove vp from the active chain
  2074. if( prv != NULL )
  2075. prv->link = vp->link;
  2076. else
  2077. {
  2078. assert( vp == p->chArray[i].active );
  2079. // vp is first recd on active chain, nvp becomes first ...
  2080. p->chArray[i].active = vp->link;
  2081. prv = NULL; // ... so prv must be NULL
  2082. }
  2083. // insert this voice on the available chain
  2084. vp->link = p->avail;
  2085. p->avail = vp;
  2086. --p->activeVoiceCnt;
  2087. vp = nvp;
  2088. }
  2089. }
  2090. }
  2091. return cmOkRC;
  2092. }
  2093. //------------------------------------------------------------------------------------------------------------
  2094. cmWtVoice* cmWtVoiceAlloc( cmCtx* ctx, cmWtVoice* ap, unsigned procSmpCnt, cmReal_t hz )
  2095. {
  2096. cmWtVoice* p = cmObjAlloc( cmWtVoice, ctx, ap );
  2097. if( procSmpCnt != 0 )
  2098. if( cmWtVoiceInit( p, procSmpCnt, hz ) != cmOkRC )
  2099. cmWtVoiceFree(&p);
  2100. return p;
  2101. }
  2102. cmRC_t cmWtVoiceFree( cmWtVoice** pp )
  2103. {
  2104. cmRC_t rc = cmOkRC;
  2105. if( pp==NULL || *pp==NULL )
  2106. return cmOkRC;
  2107. cmWtVoice* p = *pp;
  2108. if((rc = cmWtVoiceFinal(p)) != cmOkRC )
  2109. return rc;
  2110. cmMemPtrFree(&p->outV);
  2111. cmObjFree(pp);
  2112. return rc;
  2113. }
  2114. cmRC_t cmWtVoiceInit( cmWtVoice* p, unsigned procSmpCnt, cmReal_t hz )
  2115. {
  2116. p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt );
  2117. p->outN = procSmpCnt;
  2118. p->hz = hz;
  2119. p->level = 0;
  2120. p->durSmpCnt = 0;
  2121. p->phase = 0;
  2122. p->state = kOffWtId;
  2123. return cmOkRC;
  2124. }
  2125. cmRC_t cmWtVoiceFinal( cmWtVoice* p )
  2126. { return cmOkRC; }
  2127. int cmWtVoiceExec( cmWtVoice* p, struct cmMidiVoice_str* mvp, unsigned sel, cmSample_t* outChArray[], unsigned outChCnt )
  2128. {
  2129. switch( sel )
  2130. {
  2131. case kAttackMsId:
  2132. p->state = kAtkWtId;
  2133. p->hz = (13.75 * pow(2,(-9.0/12.0))) * pow(2,((double)mvp->pitch / 12));
  2134. //printf("%fhz\n",p->hz);
  2135. break;
  2136. case kReleaseMsId:
  2137. p->state = kRlsWtId;
  2138. //printf("rls:%f\n",p->phase);
  2139. break;
  2140. case kDspMsId:
  2141. {
  2142. if( p->state == kRlsWtId )
  2143. {
  2144. p->state = kOffWtId;
  2145. return 0;
  2146. }
  2147. cmMidiSynth* sp = mvp->chPtr->synthPtr;
  2148. cmSample_t* dp = outChCnt == 0 ? p->outV : outChArray[0];
  2149. cmSample_t* ep = dp + p->outN;
  2150. cmReal_t rps = (2.0 * M_PI * p->hz) / sp->srate;
  2151. cmReal_t sum=0;
  2152. unsigned i=0;
  2153. for(; dp < ep; ++dp)
  2154. {
  2155. *dp += (cmSample_t)(0.5 * sin( p->phase ));
  2156. sum += *dp;
  2157. ++i;
  2158. p->phase += rps;
  2159. }
  2160. //printf("(%f %f %i %i %p) ",p->phase,sum,i,p->outN,outChArray[0] );
  2161. }
  2162. break;
  2163. default:
  2164. assert(0);
  2165. break;
  2166. }
  2167. return 1;
  2168. }
  2169. //------------------------------------------------------------------------------------------------------------
  2170. cmWtVoiceBank* cmWtVoiceBankAlloc( cmCtx* ctx, cmWtVoiceBank* ap, double srate, unsigned procSmpCnt, unsigned voiceCnt, unsigned chCnt )
  2171. {
  2172. cmWtVoiceBank* p = cmObjAlloc( cmWtVoiceBank, ctx, ap );
  2173. if( srate != 0 )
  2174. if( cmWtVoiceBankInit( p, srate, procSmpCnt, voiceCnt, chCnt ) != cmOkRC )
  2175. cmWtVoiceBankFree(&p);
  2176. return p;
  2177. }
  2178. cmRC_t cmWtVoiceBankFree( cmWtVoiceBank** pp )
  2179. {
  2180. cmRC_t rc;
  2181. if( pp==NULL || *pp==NULL)
  2182. return cmOkRC;
  2183. cmWtVoiceBank* p = *pp;
  2184. if((rc = cmWtVoiceBankFinal(p)) != cmOkRC )
  2185. return rc;
  2186. cmMemPtrFree(&p->voiceArray);
  2187. cmMemPtrFree(&p->chArray);
  2188. cmMemPtrFree(&p->buf);
  2189. cmObjFree(pp);
  2190. return rc;
  2191. }
  2192. cmRC_t cmWtVoiceBankInit( cmWtVoiceBank* p, double srate, unsigned procSmpCnt, unsigned voiceCnt, unsigned chCnt )
  2193. {
  2194. cmRC_t rc;
  2195. unsigned i;
  2196. if((rc = cmWtVoiceBankFinal(p)) != cmOkRC )
  2197. return rc;
  2198. p->voiceArray = cmMemResizeZ( cmWtVoice*, p->voiceArray, voiceCnt );
  2199. for(i=0; i<voiceCnt; ++i)
  2200. p->voiceArray[i] = cmWtVoiceAlloc(p->obj.ctx,NULL,procSmpCnt,0);
  2201. p->voiceCnt = voiceCnt;
  2202. p->buf = cmMemResizeZ( cmSample_t, p->buf, chCnt * procSmpCnt );
  2203. p->chArray = cmMemResizeZ( cmSample_t*, p->chArray, chCnt );
  2204. for(i=0; i<chCnt; ++i)
  2205. p->chArray[i] = p->buf + (i*procSmpCnt);
  2206. p->chCnt = chCnt;
  2207. p->procSmpCnt = procSmpCnt;
  2208. return cmOkRC;
  2209. }
  2210. cmRC_t cmWtVoiceBankFinal( cmWtVoiceBank* p )
  2211. {
  2212. unsigned i;
  2213. for(i=0; i<p->voiceCnt; ++i)
  2214. cmWtVoiceFree(&p->voiceArray[i]);
  2215. return cmOkRC;
  2216. }
  2217. int cmWtVoiceBankExec( cmWtVoiceBank* p, struct cmMidiVoice_str* voicePtr, unsigned sel, cmSample_t* outChArray[], unsigned outChCnt )
  2218. {
  2219. cmWtVoice* vp = p->voiceArray[ voicePtr->index ];
  2220. bool fl = outChArray==NULL || outChCnt==0;
  2221. cmSample_t** chArray = fl ? p->chArray : outChArray;
  2222. unsigned chCnt = fl ? p->chCnt : outChCnt;
  2223. return cmWtVoiceExec( vp, voicePtr, sel, chArray, chCnt );
  2224. }
  2225. //------------------------------------------------------------------------------------------------------------
  2226. cmAudioFileBuf* cmAudioFileBufAlloc( cmCtx* ctx, cmAudioFileBuf* ap, unsigned procSmpCnt, const char* fn, unsigned audioChIdx, unsigned begSmpIdx, unsigned durSmpCnt )
  2227. {
  2228. cmAudioFileBuf* p = cmObjAlloc( cmAudioFileBuf, ctx, ap );
  2229. if( procSmpCnt != 0 )
  2230. if( cmAudioFileBufInit( p, procSmpCnt, fn, audioChIdx, begSmpIdx, durSmpCnt ) != cmOkRC )
  2231. cmAudioFileBufFree(&p);
  2232. return p;
  2233. }
  2234. cmRC_t cmAudioFileBufFree( cmAudioFileBuf** pp )
  2235. {
  2236. cmRC_t rc;
  2237. if( pp==NULL || *pp==NULL)
  2238. return cmOkRC;
  2239. cmAudioFileBuf* p = *pp;
  2240. if((rc = cmAudioFileBufFinal(p)) != cmOkRC )
  2241. return rc;
  2242. cmMemPtrFree(&p->bufV);
  2243. cmMemPtrFree(&p->fn);
  2244. cmObjFree(pp);
  2245. return rc;
  2246. }
  2247. cmRC_t cmAudioFileBufInit( cmAudioFileBuf* p, unsigned procSmpCnt, const char* fn, unsigned audioChIdx, unsigned begSmpIdx, unsigned durSmpCnt )
  2248. {
  2249. cmAudioFileH_t afH;
  2250. cmRC_t rc;
  2251. if((rc = cmAudioFileBufFinal(p)) != cmOkRC )
  2252. return rc;
  2253. // open the audio file for reading
  2254. if( cmAudioFileIsValid( afH = cmAudioFileNewOpen( fn, &p->info, &rc, p->obj.err.rpt ))==false || rc != kOkAfRC )
  2255. return cmCtxRtCondition(&p->obj, cmArgAssertRC,"The audio file '%s' could not be opend.",fn );
  2256. // validate the audio channel
  2257. if( audioChIdx >= p->info.chCnt )
  2258. return cmCtxRtCondition(&p->obj, cmArgAssertRC,"The audio file channel index %i is out of range for the audio file '%s'.",audioChIdx,fn);
  2259. // validate the start sample index
  2260. if( begSmpIdx > p->info.frameCnt )
  2261. return cmCtxRtCondition(&p->obj, cmOkRC, "The start sample index %i is past the end of the audio file '%s'.",begSmpIdx,fn);
  2262. if( durSmpCnt == cmInvalidCnt )
  2263. durSmpCnt = p->info.frameCnt - begSmpIdx;
  2264. // validate the duration
  2265. if( begSmpIdx + durSmpCnt > p->info.frameCnt )
  2266. {
  2267. unsigned newDurSmpCnt = p->info.frameCnt - begSmpIdx;
  2268. cmCtxRtCondition(&p->obj, cmOkRC, "The selected sample duration %i is past the end of the audio file '%s' and has been shorted to %i samples.",durSmpCnt,fn,newDurSmpCnt);
  2269. durSmpCnt = newDurSmpCnt;
  2270. }
  2271. // seek to the starting sample
  2272. if( cmAudioFileSeek( afH, begSmpIdx ) != kOkAfRC )
  2273. return cmCtxRtCondition(&p->obj, cmArgAssertRC,"Seek to sample index %i failed on the audio file '%s'.",begSmpIdx,fn);
  2274. // allocate the buffer memory
  2275. p->bufV = cmMemResizeZ( cmSample_t, p->bufV, durSmpCnt );
  2276. p->fn = cmMemResize( char, p->fn, strlen(fn)+1 );
  2277. p->bufN = durSmpCnt;
  2278. p->begSmpIdx = begSmpIdx;
  2279. p->chIdx = audioChIdx;
  2280. strcpy(p->fn,fn);
  2281. cmSample_t* outV = p->bufV;
  2282. // read the file into the buffer
  2283. unsigned rdSmpCnt = cmMin(4096,durSmpCnt);
  2284. unsigned cmc = 0;
  2285. while( cmc < durSmpCnt )
  2286. {
  2287. unsigned actualReadCnt = 0;
  2288. unsigned n = rdSmpCnt;
  2289. cmSample_t* chArray[] = {outV};
  2290. if( cmc + n > durSmpCnt )
  2291. n = durSmpCnt - cmc;
  2292. if((rc=cmAudioFileReadSample( afH, n, audioChIdx, 1, chArray, &actualReadCnt)) != kOkAfRC )
  2293. break;
  2294. cmc += actualReadCnt;
  2295. outV += actualReadCnt;
  2296. }
  2297. if( rc==kOkAfRC || (rc != kOkAfRC && cmAudioFileIsEOF(afH)))
  2298. rc = cmOkRC;
  2299. return rc;
  2300. }
  2301. cmRC_t cmAudioFileBufFinal(cmAudioFileBuf* p )
  2302. { return cmOkRC; }
  2303. unsigned cmAudioFileBufExec( cmAudioFileBuf* p, unsigned smpIdx, cmSample_t* outV, unsigned outN, bool sumIntoOutFl )
  2304. {
  2305. if( outV == NULL || outN == 0 || smpIdx >= p->bufN )
  2306. return 0;
  2307. unsigned n = cmMin(outN,p->bufN-smpIdx);
  2308. if( sumIntoOutFl )
  2309. cmVOS_AddVV(outV,n,p->bufV + smpIdx);
  2310. else
  2311. cmVOS_Copy(outV,n,p->bufV + smpIdx );
  2312. if( n < outN )
  2313. memset(outV+n,0,(outN-n)*sizeof(cmSample_t));
  2314. return n;
  2315. }
  2316. //------------------------------------------------------------------------------------------------------------
  2317. cmMDelay* cmMDelayAlloc( cmCtx* ctx, cmMDelay* ap, unsigned procSmpCnt, cmReal_t srate, cmReal_t fbCoeff, unsigned delayCnt, const cmReal_t* delayMsArray, const cmReal_t* delayGainArray )
  2318. {
  2319. cmMDelay* p = cmObjAlloc( cmMDelay, ctx, ap );
  2320. if( procSmpCnt != 0 )
  2321. if( cmMDelayInit( p, procSmpCnt, srate, fbCoeff, delayCnt, delayMsArray, delayGainArray ) != cmOkRC )
  2322. cmMDelayFree(&p);
  2323. return p;
  2324. }
  2325. cmRC_t cmMDelayFree( cmMDelay** pp )
  2326. {
  2327. cmRC_t rc;
  2328. if( pp == NULL || *pp==NULL)
  2329. return cmOkRC;
  2330. cmMDelay* p = *pp;
  2331. if((rc = cmMDelayFinal(p)) != cmOkRC )
  2332. return rc;
  2333. unsigned i;
  2334. for(i=0; i<p->delayCnt; ++i)
  2335. cmMemPtrFree(&p->delayArray[i].delayBuf);
  2336. cmMemPtrFree(&p->delayArray);
  2337. cmMemPtrFree(&p->outV);
  2338. cmObjFree(pp);
  2339. return cmOkRC;
  2340. }
  2341. cmRC_t cmMDelayInit( cmMDelay* p, unsigned procSmpCnt, cmReal_t srate, cmReal_t fbCoeff, unsigned delayCnt, const cmReal_t* delayMsArray, const cmReal_t* delayGainArray )
  2342. {
  2343. cmRC_t rc;
  2344. if((rc = cmMDelayFinal(p)) != cmOkRC )
  2345. return rc;
  2346. if( delayCnt <= 0 )
  2347. return rc;
  2348. p->delayArray = cmMemResizeZ( cmMDelayHead, p->delayArray, delayCnt );
  2349. unsigned i;
  2350. for(i=0; i<delayCnt; ++i)
  2351. {
  2352. p->delayArray[i].delayGain = delayGainArray == NULL ? 1.0 : delayGainArray[i];
  2353. p->delayArray[i].delayMs = delayMsArray[i];
  2354. p->delayArray[i].delaySmpFrac = delayMsArray[i] * srate / 1000.0;
  2355. p->delayArray[i].delayBufSmpCnt = ceil(delayMsArray[i] * srate / 1000)+2;
  2356. p->delayArray[i].delayBuf = cmMemResizeZ( cmSample_t, p->delayArray[i].delayBuf, p->delayArray[i].delayBufSmpCnt );
  2357. p->delayArray[i].inIdx = 0;
  2358. }
  2359. p->delayCnt= delayCnt;
  2360. p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt );
  2361. p->outN = procSmpCnt;
  2362. p->fbCoeff = fbCoeff;
  2363. p->srate = srate;
  2364. return cmOkRC;
  2365. }
  2366. cmRC_t cmMDelayFinal( cmMDelay* p )
  2367. { return cmOkRC; }
  2368. void _cmMDelayExec( cmMDelay* p, cmMDelayHead* hp, const cmSample_t inV[], cmSample_t outV[], unsigned sigN )
  2369. {
  2370. cmSample_t* dl = hp->delayBuf; // ptr to the base of the delay line
  2371. cmReal_t dfi = (cmReal_t)(hp->inIdx - hp->delaySmpFrac) + hp->delayBufSmpCnt; // fractional delay in samples
  2372. int dii0 = ((int)dfi) % hp->delayBufSmpCnt; // index to the sample just before the delay position
  2373. int dii1 = (dii0 + 1) % hp->delayBufSmpCnt; // index to the sample just after the delay position
  2374. //cmReal_t frac = 0; //dfi - dii0; // interpolation coeff.
  2375. unsigned i;
  2376. for(i=0; i<sigN; i++)
  2377. {
  2378. /*
  2379. outPtr[i] = -(((f+0)*(f-1)*(f-2)/6) * _wtPtr[iPhs0])
  2380. +(((f+1)*(f-1)*(f-2)/2) * _wtPtr[iPhs0+1])
  2381. -(((f+1)*(f-0)*(f-2)/2) * _wtPtr[iPhs0+2])
  2382. +(((f+1)*(f-0)*(f-1)/6) * _wtPtr[iPhs0+3]);
  2383. */
  2384. cmSample_t outSmp = dl[dii0]; // + (frac * (dl[dii1]-dl[dii0]));
  2385. outV[i] += outSmp/p->delayCnt;
  2386. dl[hp->inIdx] = (p->fbCoeff * outSmp) + inV[i];
  2387. hp->inIdx = (hp->inIdx+1) % hp->delayBufSmpCnt;
  2388. dii0 = (dii0+1) % hp->delayBufSmpCnt;
  2389. dii1 = (dii1+1) % hp->delayBufSmpCnt;
  2390. }
  2391. }
  2392. cmRC_t cmMDelayExec( cmMDelay* p, const cmSample_t* inV, cmSample_t* outV, unsigned sigN, bool bypassFl )
  2393. {
  2394. assert( sigN <= p->outN);
  2395. if( outV == NULL )
  2396. {
  2397. outV = p->outV;
  2398. sigN = cmMin(sigN,p->outN);
  2399. cmVOS_Fill(outV,sigN,0);
  2400. }
  2401. else
  2402. {
  2403. cmVOS_Zero(outV,sigN);
  2404. }
  2405. if( inV == NULL )
  2406. return cmOkRC;
  2407. if( bypassFl )
  2408. {
  2409. memcpy(outV,inV,sigN*sizeof(cmSample_t));
  2410. return cmOkRC;
  2411. }
  2412. unsigned di;
  2413. for( di=0; di<p->delayCnt; ++di)
  2414. {
  2415. cmMDelayHead* hp = p->delayArray + di;
  2416. hp->delaySmpFrac = hp->delayMs * p->srate / 1000.0;
  2417. _cmMDelayExec(p,hp,inV,outV,sigN);
  2418. }
  2419. return cmOkRC;
  2420. }
  2421. void cmMDelaySetTapMs( cmMDelay* p, unsigned tapIdx, cmReal_t ms )
  2422. {
  2423. assert( tapIdx < p->delayCnt );
  2424. p->delayArray[tapIdx].delayMs = ms;
  2425. }
  2426. void cmMDelaySetTapGain(cmMDelay* p, unsigned tapIdx, cmReal_t gain )
  2427. {
  2428. assert( tapIdx < p->delayCnt );
  2429. p->delayArray[tapIdx].delayGain = gain;
  2430. }
  2431. void cmMDelayReport( cmMDelay* p, cmRpt_t* rpt )
  2432. {
  2433. cmRptPrintf(rpt,"tap cnt:%i fb:%f sr:%f\n",p->delayCnt,p->fbCoeff,p->srate);
  2434. }
  2435. //------------------------------------------------------------------------------------------------------------
  2436. cmAudioSegPlayer* cmAudioSegPlayerAlloc( cmCtx* ctx, cmAudioSegPlayer* ap, unsigned procSmpCnt, unsigned outChCnt )
  2437. {
  2438. cmAudioSegPlayer* p = cmObjAlloc( cmAudioSegPlayer, ctx, ap );
  2439. if( procSmpCnt != 0 )
  2440. if( cmAudioSegPlayerInit( p, procSmpCnt, outChCnt ) != cmOkRC )
  2441. cmAudioSegPlayerFree(&p);
  2442. return p;
  2443. }
  2444. cmRC_t cmAudioSegPlayerFree( cmAudioSegPlayer** pp )
  2445. {
  2446. if( pp == NULL || *pp == NULL )
  2447. return cmOkRC;
  2448. cmAudioSegPlayer* p = *pp;
  2449. cmMemPtrFree(&p->segArray);
  2450. cmMemPtrFree(&p->outM);
  2451. cmObjFree(pp);
  2452. return cmOkRC;
  2453. }
  2454. cmRC_t cmAudioSegPlayerInit( cmAudioSegPlayer* p, unsigned procSmpCnt, unsigned outChCnt )
  2455. {
  2456. cmRC_t rc = cmOkRC;
  2457. if((rc = cmAudioSegPlayerFinal(p)) != cmOkRC )
  2458. return rc;
  2459. p->procSmpCnt = procSmpCnt;
  2460. p->outChCnt = outChCnt;
  2461. p->segCnt = 0;
  2462. if( outChCnt )
  2463. {
  2464. unsigned i;
  2465. p->outM = cmMemResizeZ( cmSample_t, p->outM, procSmpCnt * outChCnt );
  2466. p->outChArray = cmMemResizeZ( cmSample_t*, p->outChArray, outChCnt );
  2467. for(i=0; i<outChCnt; ++i)
  2468. p->outChArray[i] = p->outM + (i*procSmpCnt);
  2469. }
  2470. return rc;
  2471. }
  2472. cmRC_t cmAudioSegPlayerFinal( cmAudioSegPlayer* p )
  2473. { return cmOkRC; }
  2474. cmRC_t _cmAudioSegPlayerSegSetup( cmAudioSeg* sp, unsigned id, cmAudioFileBuf* bufPtr, unsigned smpIdx, unsigned smpCnt, unsigned outChIdx )
  2475. {
  2476. sp->bufPtr = bufPtr;
  2477. sp->id = id;
  2478. sp->smpIdx = smpIdx;
  2479. sp->smpCnt = smpCnt;
  2480. sp->outChIdx = outChIdx;
  2481. sp->outSmpIdx = 0;
  2482. sp->flags = 0;
  2483. return cmOkRC;
  2484. }
  2485. cmAudioSeg* _cmAudioSegPlayerIdToSegPtr( cmAudioSegPlayer* p, unsigned id, bool ignoreErrFl )
  2486. {
  2487. unsigned i = 0;
  2488. for(i=0; i<p->segCnt; ++i)
  2489. if( p->segArray[i].id == id )
  2490. return p->segArray + i;
  2491. if( !ignoreErrFl )
  2492. cmCtxRtCondition(&p->obj, cmArgAssertRC,"Unable to locate an audio segment with id=%i.",id);
  2493. return NULL;
  2494. }
  2495. cmRC_t cmAudioSegPlayerInsert( cmAudioSegPlayer* p, unsigned id, cmAudioFileBuf* bufPtr, unsigned smpIdx, unsigned smpCnt, unsigned outChIdx )
  2496. {
  2497. cmRC_t rc;
  2498. assert( _cmAudioSegPlayerIdToSegPtr( p, id, true ) == NULL );
  2499. p->segArray = cmMemResizePZ( cmAudioSeg, p->segArray, p->segCnt + 1 );
  2500. cmAudioSeg* sp = p->segArray + p->segCnt;
  2501. if((rc = _cmAudioSegPlayerSegSetup( sp, id, bufPtr, smpIdx, smpCnt, outChIdx )) == cmOkRC )
  2502. ++p->segCnt;
  2503. return rc;
  2504. }
  2505. cmRC_t cmAudioSegPlayerEdit( cmAudioSegPlayer* p, unsigned id, cmAudioFileBuf* bufPtr, unsigned smpIdx, unsigned smpCnt, unsigned outChIdx )
  2506. {
  2507. cmAudioSeg* sp = _cmAudioSegPlayerIdToSegPtr(p,id,false);
  2508. return _cmAudioSegPlayerSegSetup( sp, id, bufPtr, smpIdx, smpCnt, outChIdx );
  2509. }
  2510. cmRC_t cmAudioSegPlayerRemove( cmAudioSegPlayer* p, unsigned id, bool delFl )
  2511. {
  2512. cmAudioSeg* sp = _cmAudioSegPlayerIdToSegPtr(p,id,false);
  2513. if( sp == NULL )
  2514. return cmArgAssertRC;
  2515. sp->flags = cmEnaFlag( sp->flags, kDelAspFl, delFl );
  2516. return cmOkRC;
  2517. }
  2518. cmRC_t cmAudioSegPlayerEnable( cmAudioSegPlayer* p, unsigned id, bool enableFl, unsigned outSmpIdx )
  2519. {
  2520. cmAudioSeg* sp = _cmAudioSegPlayerIdToSegPtr(p,id,false);
  2521. if( sp == NULL )
  2522. return cmArgAssertRC;
  2523. if( outSmpIdx != cmInvalidIdx )
  2524. sp->outSmpIdx = outSmpIdx;
  2525. sp->flags = cmEnaFlag( sp->flags, kEnableAspFl, enableFl );
  2526. return cmOkRC;
  2527. }
  2528. void _cmAudioSegPlayerResetSeg( cmAudioSeg* sp )
  2529. {
  2530. sp->outSmpIdx = 0;
  2531. sp->flags = cmClrFlag(sp->flags, kEnableAspFl );
  2532. }
  2533. cmRC_t cmAudioSegPlayerReset( cmAudioSegPlayer* p )
  2534. {
  2535. unsigned i;
  2536. for(i=0; i<p->segCnt; ++i)
  2537. {
  2538. cmAudioSeg* sp = p->segArray + i;
  2539. _cmAudioSegPlayerResetSeg(sp);
  2540. }
  2541. return cmOkRC;
  2542. }
  2543. cmRC_t cmAudioSegPlayerExec( cmAudioSegPlayer* p, cmSample_t** outChPtr, unsigned outChCnt, unsigned procSmpCnt )
  2544. {
  2545. unsigned i;
  2546. if( outChPtr == NULL || outChCnt == 0 )
  2547. {
  2548. assert( p->outChCnt > 0 );
  2549. outChPtr = p->outChArray;
  2550. outChCnt = p->outChCnt;
  2551. assert( p->procSmpCnt <= procSmpCnt );
  2552. }
  2553. for(i=0; i<p->segCnt; ++i)
  2554. {
  2555. cmAudioSeg* sp = p->segArray + i;
  2556. // if the output channel is valid and the segment is enabled and not deleted
  2557. if( sp->outChIdx < outChCnt && (sp->flags & (kEnableAspFl | kDelAspFl)) == kEnableAspFl )
  2558. {
  2559. unsigned bufSmpIdx = sp->smpIdx + sp->outSmpIdx;
  2560. unsigned bufSmpCnt = 0;
  2561. // if all the samples have been played
  2562. if( sp->bufPtr->bufN <= bufSmpIdx )
  2563. _cmAudioSegPlayerResetSeg(sp);
  2564. else
  2565. {
  2566. // prevent playing past the end of the buffer
  2567. bufSmpCnt = cmMin( procSmpCnt, sp->bufPtr->bufN - bufSmpIdx );
  2568. // limit the number of samples to the segment length
  2569. bufSmpCnt = cmMin( bufSmpCnt, sp->smpCnt - sp->outSmpIdx );
  2570. // sum the samples into the output channel
  2571. cmVOS_AddVV( outChPtr[ sp->outChIdx ], bufSmpCnt, sp->bufPtr->bufV + bufSmpIdx );
  2572. // incr the next output sample index
  2573. sp->outSmpIdx += bufSmpCnt;
  2574. }
  2575. if( bufSmpCnt < procSmpCnt )
  2576. cmVOS_Zero( outChPtr[ sp->outChIdx ] + bufSmpCnt, procSmpCnt - bufSmpCnt );
  2577. }
  2578. }
  2579. return cmOkRC;
  2580. }
  2581. //------------------------------------------------------------------------------------------------------------
  2582. /*
  2583. cmCluster0* cmCluster0Alloc( cmCtx* ctx, cmCluster0* ap, unsigned stateCnt, unsigned binCnt, unsigned flags, cmCluster0DistFunc_t distFunc, void* dstUserPtr )
  2584. {
  2585. cmCluster0* p = cmObjAlloc( cmCluster0, ctx, ap );
  2586. if( stateCnt != 0 )
  2587. if( cmCluster0Init( p, stateCnt, binCnt, flags, distFunc, distUserPtr ) != cmOkRC )
  2588. cmCluster0Free(&p);
  2589. return p;
  2590. }
  2591. cmRC_t cmCluster0Free( cmCluster0** pp )
  2592. {
  2593. if( pp == NULL || *pp == NULL )
  2594. return cmOkRC;
  2595. cmCluster0* p = *pp;
  2596. cmMemPtrFree(&p->oM);
  2597. cmMemPtrFree(&p->tM);
  2598. cmMemPtrFree(&p->dV);
  2599. cmObjFree(pp);
  2600. return cmOkRC;
  2601. }
  2602. cmRC_t cmCluster0Init( cmCluster0* p, unsigned stateCnt, unsigned binCnt, unsigned flags, cmCluster0DistFunc_t distFunc, void* distUserPtr )
  2603. {
  2604. cmRC_t rc;
  2605. if((rc = cmCluster0Final(p)) != cmOkRC )
  2606. return rc;
  2607. p->oM = cmMemResizeZ( cmReal_t, p->oM, binCnt * stateCnt );
  2608. p->tM = cmMemResizeZ( cmReal_t, p->tM, stateCnt * stateCnt );
  2609. p->stateCnt = stateCnt;
  2610. p->binCnt = binCnt;
  2611. p->flags = flags;
  2612. p->distFunc = distFunc;
  2613. p->distUserPtr = distUserPtr;
  2614. p->cnt = 0;
  2615. }
  2616. cmRC_t cmCluster0Final( cmCluster0* p )
  2617. { return cmOkRC; }
  2618. cmRC_t cmCluster0Exec( cmCluster0* p, const cmReal_t* v, unsigned vn )
  2619. {
  2620. assert( vn <= p->binCnt );
  2621. ++cnt;
  2622. if( cnt <= stateCnt )
  2623. {
  2624. cmVOR_Copy( p->oM + ((cnt-1)*binCnt), vn, v );
  2625. return cmOkRC;
  2626. }
  2627. return cmOkRC;
  2628. }
  2629. */
  2630. cmNmf_t* cmNmfAlloc( cmCtx* ctx, cmNmf_t* ap, unsigned n, unsigned m, unsigned r, unsigned maxIterCnt, unsigned convergeCnt )
  2631. {
  2632. cmNmf_t* p = cmObjAlloc( cmNmf_t, ctx, ap );
  2633. if( n != 0 )
  2634. if( cmNmfInit( p, n, m, r, maxIterCnt, convergeCnt ) != cmOkRC )
  2635. cmNmfFree(&p);
  2636. return p;
  2637. }
  2638. cmRC_t cmNmfFree( cmNmf_t** pp )
  2639. {
  2640. if( pp== NULL || *pp == NULL )
  2641. return cmOkRC;
  2642. cmNmf_t* p = *pp;
  2643. cmMemPtrFree(&p->V);
  2644. cmMemPtrFree(&p->W);
  2645. cmMemPtrFree(&p->H);
  2646. cmMemPtrFree(&p->tr);
  2647. cmMemPtrFree(&p->x);
  2648. cmMemPtrFree(&p->t0nm);
  2649. cmMemPtrFree(&p->t1nm);
  2650. cmMemPtrFree(&p->Wt);
  2651. cmMemPtrFree(&p->trm);
  2652. cmMemPtrFree(&p->crm);
  2653. cmMemPtrFree(&p->c0);
  2654. cmMemPtrFree(&p->c1);
  2655. cmMemPtrFree(&p->idxV);
  2656. cmObjFree(pp);
  2657. return cmOkRC;
  2658. }
  2659. cmRC_t cmNmfInit( cmNmf_t* p, unsigned n, unsigned m, unsigned r, unsigned maxIterCnt, unsigned convergeCnt )
  2660. {
  2661. cmRC_t rc;
  2662. if((rc = cmNmfFinal(p)) != cmOkRC )
  2663. return rc;
  2664. p->n = n;
  2665. p->m = m;
  2666. p->r = r;
  2667. p->maxIterCnt = maxIterCnt;
  2668. p->convergeCnt= convergeCnt;
  2669. p->V = cmMemResizeZ(cmReal_t, p->V, n*m );
  2670. p->W = cmMemResize( cmReal_t, p->W, n*r );
  2671. p->H = cmMemResize( cmReal_t, p->H, r*m );
  2672. p->tr = cmMemResize( cmReal_t, p->tr, r );
  2673. p->x = cmMemResize( cmReal_t, p->x, r*cmMax(m,n) );
  2674. p->t0nm = cmMemResize( cmReal_t, p->t0nm, cmMax(r,n)*m );
  2675. p->Ht = p->t0nm;
  2676. p->t1nm = cmMemResize( cmReal_t, p->t1nm, n*m );
  2677. p->Wt = cmMemResize( cmReal_t, p->Wt, r*n );
  2678. p->trm = cmMemResize( cmReal_t, p->trm, r*cmMax(m,n) );
  2679. p->crm = cmMemResizeZ(unsigned, p->crm, r*m);
  2680. p->tnr = p->trm;
  2681. p->c0 = cmMemResizeZ(unsigned, p->c0, m*m);
  2682. p->c1 = cmMemResizeZ(unsigned, p->c1, m*m);
  2683. p->idxV = cmMemResizeZ(unsigned, p->idxV, m );
  2684. p->c0m = p->c0;
  2685. p->c1m = p->c1;
  2686. cmVOR_Random(p->W,n*r,0.0,1.0);
  2687. cmVOR_Random(p->H,r*m,0.0,1.0);
  2688. return rc;
  2689. }
  2690. cmRC_t cmNmfFinal(cmNmf_t* p )
  2691. { return cmOkRC; }
  2692. // NMF base on: Lee and Seung, 2001, Algo's for Non-negative Matrix Fcmtorization
  2693. // Connectivity stopping technique based on: http://www.broadinstitute.org/mpr/publications/projects/NMF/nmf.m
  2694. cmRC_t cmNmfExec( cmNmf_t* p, const cmReal_t* vM, unsigned cn )
  2695. {
  2696. cmRC_t rc = cmOkRC;
  2697. unsigned i,j,k;
  2698. unsigned n = p->n;
  2699. unsigned m = p->m;
  2700. unsigned r = p->r;
  2701. unsigned stopIter = 0;
  2702. assert(cn <= m );
  2703. // shift in the incoming columns of V[]
  2704. if( cn < m )
  2705. cmVOR_Shift(p->V, n*m, n*cn,0);
  2706. cmVOR_Copy( p->V, n*cn,vM );
  2707. // shift H[] by the same amount as V[]
  2708. if( cn < m )
  2709. cmVOR_Shift( p->H, r*m, r*cn,0);
  2710. cmVOR_Random(p->H, r*cn, 0.0, 1.0 );
  2711. cmVOU_Zero( p->c1m, m*m );
  2712. for(i=0,j=0; i<p->maxIterCnt && stopIter<p->convergeCnt; ++i)
  2713. {
  2714. // x[r,m] =repmat(sum(W,1)',1,m);
  2715. cmVOR_SumM( p->W, n, r, p->tr );
  2716. for(j=0; j<m; ++j)
  2717. cmVOR_Copy( p->x + (j*r), r, p->tr );
  2718. cmVOR_Transpose(p->Wt,p->W,n,r);
  2719. //H=H.*(W'*(V./(W*H)))./x;
  2720. cmVOR_MultMMM(p->t0nm,n,m,p->W,p->H,r); // t0nm[n,m] = W*H
  2721. cmVOR_DivVVV( p->t1nm,n*m,p->V,p->t0nm); // t1nm[n,m] = V./(W*H)
  2722. cmVOR_MultMMM(p->trm,r,m,p->Wt,p->t1nm,n); // trm[r,m] = W'*(V./(W*H))
  2723. cmVOR_MultVV(p->H,r*m,p->trm); // H[r,m] = H .* (W'*(V./(W*H)))
  2724. cmVOR_DivVV(p->H,r*m, p->x ); // H[r,m] = (H .* (W'*(V./(W*H)))) ./ x
  2725. // x[n,r]=repmat(sum(H,2)',n,1);
  2726. cmVOR_SumMN(p->H, r, m, p->tr );
  2727. for(j=0; j<n; ++j)
  2728. cmVOR_CopyN(p->x + j, r, n, p->tr, 1 );
  2729. cmVOR_Transpose(p->Ht,p->H,r,m);
  2730. // W=W.*((V./(W*H))*H')./x;
  2731. cmVOR_MultMMM(p->tnr,n,r,p->t1nm,p->Ht,m); // tnr[n,r] = (V./(W*H))*Ht
  2732. cmVOR_MultVV(p->W,n*r,p->tnr); // W[n,r] = W.*(V./(W*H))*Ht
  2733. cmVOR_DivVV(p->W,n*r,p->x); // W[n,r] = W.*(V./(W*H))*Ht ./x
  2734. if( i % 10 == 0 )
  2735. {
  2736. cmVOR_ReplaceLte( p->H, r*m, p->H, 2.2204e-16, 2.2204e-16 );
  2737. cmVOR_ReplaceLte( p->W, n*r, p->W, 2.2204e-16, 2.2204e-16 );
  2738. cmVOR_MaxIndexM( p->idxV, p->H, r, m );
  2739. unsigned mismatchCnt = 0;
  2740. for(j=0; j<m; ++j)
  2741. for(k=0; k<m; ++k)
  2742. {
  2743. unsigned c_idx = (j*m)+k;
  2744. p->c0m[ c_idx ] = p->idxV[j] == p->idxV[k];
  2745. mismatchCnt += p->c0m[ c_idx ] != p->c1m[ c_idx ];
  2746. }
  2747. if( mismatchCnt == 0 )
  2748. ++stopIter;
  2749. else
  2750. stopIter = 0;
  2751. printf("%i %i %i\n",i,stopIter,mismatchCnt);
  2752. fflush(stdout);
  2753. unsigned* tcm = p->c0m;
  2754. p->c0m = p->c1m;
  2755. p->c1m = tcm;
  2756. }
  2757. }
  2758. return rc;
  2759. }
  2760. //------------------------------------------------------------------------------------------------------------
  2761. unsigned _cmVectArrayTypeByteCnt( cmVectArray_t* p, unsigned flags )
  2762. {
  2763. switch( flags & kVaMask )
  2764. {
  2765. case kFloatVaFl: return sizeof(float);
  2766. case kDoubleVaFl: return sizeof(double);
  2767. case kIntVaFl: return sizeof(int);
  2768. case kUIntVaFl: return sizeof(unsigned);
  2769. }
  2770. if( p != NULL )
  2771. cmCtxRtCondition(&p->obj,cmInvalidArgRC,"Unknown data type.");
  2772. return 0;
  2773. }
  2774. cmRC_t _cmVectArrayAppend( cmVectArray_t* p, const void* v, unsigned typeByteCnt, unsigned valCnt )
  2775. {
  2776. cmRC_t rc = cmSubSysFailRC;
  2777. cmVectArrayVect_t* ep = NULL;
  2778. unsigned byteCnt = typeByteCnt * valCnt;
  2779. if( byteCnt == 0 || v == NULL )
  2780. return rc;
  2781. // verify that all vectors written to this vector array contain the same data type.
  2782. if( typeByteCnt != _cmVectArrayTypeByteCnt(p,p->flags) )
  2783. return cmCtxRtCondition(&p->obj,cmInvalidArgRC,"All data stored to a cmVectArray_t must be a consistent type.");
  2784. // allocate space for the link record
  2785. if((ep = cmMemAllocZ(cmVectArrayVect_t,1)) == NULL )
  2786. goto errLabel;
  2787. // allocate space for the vector data
  2788. if((ep->u.v = cmMemAlloc(char,typeByteCnt*valCnt)) == NULL )
  2789. goto errLabel;
  2790. // append the link recd to the end of the element list
  2791. if( p->ep != NULL )
  2792. p->ep->link = ep;
  2793. else
  2794. {
  2795. p->bp = ep;
  2796. p->cur = p->bp;
  2797. }
  2798. p->ep = ep;
  2799. // store the length of the vector
  2800. ep->n = valCnt;
  2801. // copy in the vector data
  2802. memcpy(ep->u.v,v,byteCnt);
  2803. // track the number of vectors stored
  2804. p->vectCnt += 1;
  2805. // track the longest data vector
  2806. if( valCnt > p->maxEleCnt )
  2807. p->maxEleCnt = valCnt;
  2808. rc = cmOkRC;
  2809. errLabel:
  2810. if(rc != cmOkRC )
  2811. {
  2812. cmMemFree(ep->u.v);
  2813. cmMemFree(ep);
  2814. }
  2815. return rc;
  2816. }
  2817. cmVectArray_t* cmVectArrayAlloc( cmCtx* ctx, unsigned flags )
  2818. {
  2819. cmRC_t rc = cmOkRC;
  2820. cmVectArray_t* p = cmObjAlloc(cmVectArray_t,ctx,NULL);
  2821. assert(p != NULL);
  2822. switch( flags & kVaMask )
  2823. {
  2824. case kIntVaFl:
  2825. p->flags |= kIntVaFl;
  2826. p->typeByteCnt = sizeof(int);
  2827. break;
  2828. case kUIntVaFl:
  2829. p->flags |= kUIntVaFl;
  2830. p->typeByteCnt = sizeof(unsigned);
  2831. break;
  2832. case kFloatVaFl:
  2833. p->flags |= kFloatVaFl;
  2834. p->typeByteCnt = sizeof(float);
  2835. break;
  2836. case kDoubleVaFl:
  2837. p->flags |= kDoubleVaFl;
  2838. p->typeByteCnt = sizeof(double);
  2839. break;
  2840. default:
  2841. rc = cmCtxRtCondition(&p->obj,cmInvalidArgRC,"The vector array value type flag was not recognized.");
  2842. }
  2843. if(rc != cmOkRC)
  2844. cmVectArrayFree(&p);
  2845. return p;
  2846. }
  2847. cmVectArray_t* cmVectArrayAllocFromFile(cmCtx* ctx, const char* fn )
  2848. {
  2849. cmRC_t rc = cmOkRC;
  2850. FILE* fp = NULL;
  2851. char* buf = NULL;
  2852. cmVectArray_t* p = NULL;
  2853. unsigned hn = 4;
  2854. unsigned hdr[hn];
  2855. // create the file
  2856. if((fp = fopen(fn,"rb")) == NULL )
  2857. {
  2858. rc = cmCtxRtCondition(&ctx->obj,cmSystemErrorRC,"The vector array file '%s' could not be opened.",cmStringNullGuard(fn));
  2859. goto errLabel;
  2860. }
  2861. if( fread(hdr,sizeof(unsigned),hn,fp) != hn )
  2862. {
  2863. rc = cmCtxRtCondition(&ctx->obj,cmSystemErrorRC,"The vector array file header could not be read from '%s'.",cmStringNullGuard(fn));
  2864. goto errLabel;
  2865. }
  2866. unsigned flags = hdr[0];
  2867. unsigned typeByteCnt = hdr[1];
  2868. unsigned vectCnt = hdr[2];
  2869. unsigned maxEleCnt = hdr[3];
  2870. unsigned i;
  2871. buf = cmMemAlloc(char,maxEleCnt*typeByteCnt);
  2872. if((p = cmVectArrayAlloc(ctx, flags )) == NULL )
  2873. goto errLabel;
  2874. for(i=0; i<vectCnt; ++i)
  2875. {
  2876. unsigned vn;
  2877. if( fread(&vn,sizeof(unsigned),1,fp) != 1 )
  2878. {
  2879. rc = cmCtxRtCondition(&p->obj,cmSystemErrorRC,"The vector array file element count read failed on vector index:%i in '%s'.",i,cmStringNullGuard(fn));
  2880. goto errLabel;
  2881. }
  2882. assert( vn <= maxEleCnt );
  2883. if( fread(buf,typeByteCnt,vn,fp) != vn )
  2884. {
  2885. rc = cmCtxRtCondition(&p->obj,cmSystemErrorRC,"The vector array data read failed on vector index:%i in '%s'.",i,cmStringNullGuard(fn));
  2886. goto errLabel;
  2887. }
  2888. if((rc = _cmVectArrayAppend(p,buf, typeByteCnt, vn )) != cmOkRC )
  2889. {
  2890. rc = cmCtxRtCondition(&p->obj,rc,"The vector array data store failed on vector index:%i in '%s'.",i,cmStringNullGuard(fn));
  2891. goto errLabel;
  2892. }
  2893. }
  2894. errLabel:
  2895. if( fp != NULL )
  2896. fclose(fp);
  2897. cmMemFree(buf);
  2898. if(rc != cmOkRC && p != NULL)
  2899. cmVectArrayFree(&p);
  2900. return p;
  2901. }
  2902. cmRC_t cmVectArrayFree( cmVectArray_t** pp )
  2903. {
  2904. cmRC_t rc = cmOkRC;
  2905. if( pp == NULL || *pp == NULL )
  2906. return rc;
  2907. cmVectArray_t* p = *pp;
  2908. if((rc = cmVectArrayClear(p)) != cmOkRC )
  2909. return rc;
  2910. cmMemFree(p->tempV);
  2911. cmObjFree(pp);
  2912. return rc;
  2913. }
  2914. cmRC_t cmVectArrayClear( cmVectArray_t* p )
  2915. {
  2916. cmVectArrayVect_t* ep = p->bp;
  2917. while( ep!=NULL )
  2918. {
  2919. cmVectArrayVect_t* np = ep->link;
  2920. cmMemFree(ep->u.v);
  2921. cmMemFree(ep);
  2922. ep = np;
  2923. }
  2924. p->bp = NULL;
  2925. p->ep = NULL;
  2926. p->maxEleCnt = 0;
  2927. p->vectCnt = 0;
  2928. return cmOkRC;
  2929. }
  2930. unsigned cmVectArrayCount( const cmVectArray_t* p )
  2931. { return p->vectCnt; }
  2932. unsigned cmVectArrayMaxRowCount( const cmVectArray_t* p )
  2933. {
  2934. const cmVectArrayVect_t* np = p->bp;
  2935. unsigned maxN = 0;
  2936. for(; np!=NULL; np=np->link)
  2937. if( np->n > maxN )
  2938. maxN = np->n;
  2939. return maxN;
  2940. }
  2941. cmRC_t cmVectArrayAppendV( cmVectArray_t* p, const void* v, unsigned vn )
  2942. { return _cmVectArrayAppend(p,v,_cmVectArrayTypeByteCnt(p,p->flags), vn); }
  2943. cmRC_t cmVectArrayAppendS( cmVectArray_t* p, const cmSample_t* v, unsigned vn )
  2944. { return _cmVectArrayAppend(p,v,sizeof(v[0]),vn); }
  2945. cmRC_t cmVectArrayAppendR( cmVectArray_t* p, const cmReal_t* v, unsigned vn )
  2946. { return _cmVectArrayAppend(p,v,sizeof(v[0]),vn); }
  2947. cmRC_t cmVectArrayAppendF( cmVectArray_t* p, const float* v, unsigned vn )
  2948. { return _cmVectArrayAppend(p,v,sizeof(v[0]),vn); }
  2949. cmRC_t cmVectArrayAppendD( cmVectArray_t* p, const double* v, unsigned vn )
  2950. { return _cmVectArrayAppend(p,v,sizeof(v[0]),vn); }
  2951. cmRC_t cmVectArrayAppendI( cmVectArray_t* p, const int* v, unsigned vn )
  2952. { return _cmVectArrayAppend(p,v,sizeof(v[0]),vn); }
  2953. cmRC_t cmVectArrayAppendU( cmVectArray_t* p, const unsigned* v, unsigned vn )
  2954. { return _cmVectArrayAppend(p,v,sizeof(v[0]),vn); }
  2955. cmRC_t cmVectArrayWrite( cmVectArray_t* p, const char* fn )
  2956. {
  2957. cmRC_t rc = cmOkRC;
  2958. FILE* fp = NULL;
  2959. cmVectArrayVect_t* ep;
  2960. unsigned i;
  2961. unsigned hn = 4;
  2962. unsigned hdr[hn];
  2963. hdr[0] = p->flags;
  2964. hdr[1] = p->typeByteCnt;
  2965. hdr[2] = p->vectCnt;
  2966. hdr[3] = p->maxEleCnt;
  2967. // create the file
  2968. if((fp = fopen(fn,"wb")) == NULL )
  2969. return cmCtxRtCondition(&p->obj,cmSystemErrorRC,"The vector array file '%s' could not be created.",cmStringNullGuard(fn));
  2970. // write the header
  2971. if( fwrite(hdr,sizeof(unsigned),hn,fp) != hn )
  2972. {
  2973. rc = cmCtxRtCondition(&p->obj,cmSystemErrorRC,"Vector array file header write failed in '%s'.",cmStringNullGuard(fn));
  2974. goto errLabel;
  2975. }
  2976. // write each vector element
  2977. for(ep=p->bp,i=0; ep!=NULL; ep=ep->link,++i)
  2978. {
  2979. // write the count of data values in the vector
  2980. if( fwrite(&ep->n,sizeof(ep->n),1,fp) != 1 )
  2981. {
  2982. rc = cmCtxRtCondition(&p->obj,cmSystemErrorRC,"Vector array file write failed on element header %i in '%s'.",i,cmStringNullGuard(fn));
  2983. goto errLabel;
  2984. }
  2985. // write the vector
  2986. if(fwrite(ep->u.v,p->typeByteCnt,ep->n,fp) != ep->n )
  2987. {
  2988. rc = cmCtxRtCondition(&p->obj,cmSystemErrorRC,"Vector array file write failed on data vector %i in '%s'.",i,cmStringNullGuard(fn));
  2989. goto errLabel;
  2990. }
  2991. }
  2992. errLabel:
  2993. if( fp != NULL )
  2994. fclose(fp);
  2995. return rc;
  2996. }
  2997. cmRC_t cmVectArrayWriteDirFn(cmVectArray_t* p, const char* dir, const char* fn )
  2998. {
  2999. assert( dir!=NULL && fn!=NULL );
  3000. const cmChar_t* path = cmFsMakeFn( dir, fn, NULL, NULL );
  3001. cmRC_t rc = cmVectArrayWrite(p,path);
  3002. cmFsFreeFn(path);
  3003. return rc;
  3004. }
  3005. cmRC_t cmVectArrayPrint( cmVectArray_t* p, cmRpt_t* rpt )
  3006. {
  3007. cmRC_t rc = cmOkRC;
  3008. cmVectArrayVect_t* rp = p->bp;
  3009. for(; rp!=NULL; rp=rp->link)
  3010. {
  3011. switch( p->flags & kVaMask )
  3012. {
  3013. case kFloatVaFl:
  3014. cmVOF_Print(rpt,1,rp->n,rp->u.fV);
  3015. break;
  3016. case kDoubleVaFl:
  3017. cmVOD_Print(rpt,1,rp->n,rp->u.dV);
  3018. break;
  3019. case kIntVaFl:
  3020. cmVOI_Print(rpt,1,rp->n,rp->u.iV);
  3021. break;
  3022. case kUIntVaFl:
  3023. cmVOU_Print(rpt,1,rp->n,rp->u.uV);
  3024. break;
  3025. default:
  3026. rc = cmCtxRtCondition(&p->obj,cmInvalidArgRC,"The vector array value type flag was not recognized.");
  3027. break;
  3028. }
  3029. }
  3030. return rc;
  3031. }
  3032. unsigned cmVectArrayForEachS( cmVectArray_t* p, unsigned idx, unsigned cnt, cmVectArrayForEachFuncS_t func, void* arg )
  3033. {
  3034. cmVectArrayVect_t* ep = p->bp;
  3035. unsigned i = 0;
  3036. unsigned n = 0;
  3037. // for each sub-array
  3038. for(; ep!=NULL && n<cnt; ep=ep->link )
  3039. {
  3040. // if the cur sub-array is in the range of idx:idx+cnt
  3041. if( i <= idx && idx < i + ep->n )
  3042. {
  3043. unsigned j = idx - i; // starting idx into cur sub-array
  3044. assert(j<ep->n);
  3045. unsigned m = cmMin(ep->n - j,cnt-n); // cnt of ele's to send from cur sub-array
  3046. // do callback
  3047. if( func(arg, idx, ep->u.sV + j, m ) != cmOkRC )
  3048. break;
  3049. idx += m;
  3050. n += m;
  3051. }
  3052. i += ep->n;
  3053. }
  3054. return n;
  3055. }
  3056. cmRC_t _cmVectArrayWriteMatrix( cmCtx* ctx, const char* fn, unsigned flags, const void* m, unsigned rn, unsigned cn )
  3057. {
  3058. cmRC_t rc = cmOkRC;
  3059. cmVectArray_t* p;
  3060. const char* b = (const char*)m;
  3061. unsigned tbc = _cmVectArrayTypeByteCnt( NULL, flags );
  3062. unsigned ri = 0;
  3063. char* vv = cmMemAlloc(char,cn*tbc);
  3064. if((p = cmVectArrayAlloc(ctx,flags)) == NULL )
  3065. return cmCtxRtCondition(&ctx->obj,cmSubSysFailRC,"Unable to allocate a cmVectArray_t in %s().",__FUNCTION__);
  3066. for(ri=0; ri<rn; ++ri)
  3067. {
  3068. // get ptr to first element in row 'ri' or m[]
  3069. const char* v = b + ri*tbc;
  3070. unsigned ci;
  3071. // for each column in m[ri,:]
  3072. for(ci=0; ci<cn; ++ci)
  3073. memcpy(vv + ci*tbc, v + ci*rn*tbc, tbc );
  3074. // append the row to the VectArray
  3075. if((rc = cmVectArrayAppendV(p,vv,cn)) != cmOkRC )
  3076. {
  3077. rc = cmCtxRtCondition(&p->obj,rc,"Vector append failed in %s().",__FUNCTION__);
  3078. goto errLabel;
  3079. }
  3080. }
  3081. if((rc = cmVectArrayWrite(p,fn)) != cmOkRC )
  3082. rc = cmCtxRtCondition(&p->obj,rc,"Vector array write failed in %s().",__FUNCTION__);
  3083. errLabel:
  3084. if((rc = cmVectArrayFree(&p)) != cmOkRC )
  3085. rc = cmCtxRtCondition(&ctx->obj,rc,"Vector array free failed in %s().",__FUNCTION__);
  3086. cmMemFree(vv);
  3087. return rc;
  3088. }
  3089. cmRC_t cmVectArrayWriteVectorV( cmCtx* ctx, const char* fn, const void* v, unsigned vn, unsigned flags )
  3090. { return _cmVectArrayWriteMatrix( ctx, fn, flags, v, 1, vn ); }
  3091. cmRC_t cmVectArrayWriteVectorS( cmCtx* ctx, const char* fn, const cmSample_t* v, unsigned vn )
  3092. { return _cmVectArrayWriteMatrix( ctx, fn, kSampleVaFl, v, 1, vn ); }
  3093. cmRC_t cmVectArrayWriteVectorR( cmCtx* ctx, const char* fn, const cmReal_t* v, unsigned vn )
  3094. { return _cmVectArrayWriteMatrix( ctx, fn, kRealVaFl, v, 1, vn ); }
  3095. cmRC_t cmVectArrayWriteVectorD( cmCtx* ctx, const char* fn, const double* v, unsigned vn )
  3096. { return _cmVectArrayWriteMatrix( ctx, fn, kDoubleVaFl, v, 1, vn ); }
  3097. cmRC_t cmVectArrayWriteVectorF( cmCtx* ctx, const char* fn, const float* v, unsigned vn )
  3098. { return _cmVectArrayWriteMatrix( ctx, fn, kFloatVaFl, v, 1, vn ); }
  3099. cmRC_t cmVectArrayWriteVectorI( cmCtx* ctx, const char* fn, const int* v, unsigned vn )
  3100. { return _cmVectArrayWriteMatrix( ctx, fn, kIntVaFl, v, 1, vn ); }
  3101. cmRC_t cmVectArrayWriteVectorU( cmCtx* ctx, const char* fn, const unsigned* v, unsigned vn )
  3102. { return _cmVectArrayWriteMatrix( ctx, fn, kUIntVaFl, v, 1, vn ); }
  3103. cmRC_t cmVectArrayWriteMatrixV( cmCtx* ctx, const char* fn, const void* v, unsigned rn, unsigned cn, unsigned flags )
  3104. { return _cmVectArrayWriteMatrix( ctx, fn, flags, v, rn, cn); }
  3105. cmRC_t cmVectArrayWriteMatrixS( cmCtx* ctx, const char* fn, const cmSample_t* v, unsigned rn, unsigned cn )
  3106. { return _cmVectArrayWriteMatrix( ctx, fn, kSampleVaFl, v, rn, cn); }
  3107. cmRC_t cmVectArrayWriteMatrixR( cmCtx* ctx, const char* fn, const cmReal_t* v, unsigned rn, unsigned cn )
  3108. { return _cmVectArrayWriteMatrix( ctx, fn, kRealVaFl, v, rn, cn); }
  3109. cmRC_t cmVectArrayWriteMatrixD( cmCtx* ctx, const char* fn, const double* v, unsigned rn, unsigned cn )
  3110. { return _cmVectArrayWriteMatrix( ctx, fn, kDoubleVaFl, v, rn, cn); }
  3111. cmRC_t cmVectArrayWriteMatrixF( cmCtx* ctx, const char* fn, const float* v, unsigned rn, unsigned cn )
  3112. { return _cmVectArrayWriteMatrix( ctx, fn, kFloatVaFl, v, rn, cn); }
  3113. cmRC_t cmVectArrayWriteMatrixI( cmCtx* ctx, const char* fn, const int* v, unsigned rn, unsigned cn )
  3114. { return _cmVectArrayWriteMatrix( ctx, fn, kIntVaFl, v, rn, cn); }
  3115. cmRC_t cmVectArrayWriteMatrixU( cmCtx* ctx, const char* fn, const unsigned* v, unsigned rn, unsigned cn )
  3116. { return _cmVectArrayWriteMatrix( ctx, fn, kUIntVaFl, v, rn, cn); }
  3117. // Fill v[(*vnRef)*tbc] with the data from the current row of p.
  3118. // Return the count of elements copied to v[] in *vnRef.
  3119. cmRC_t _cmVectArrayGetV( cmVectArray_t* p, void* v, unsigned* vnRef, unsigned tbc )
  3120. {
  3121. assert( tbc == p->typeByteCnt );
  3122. if( cmVectArrayIsEOL(p) )
  3123. return cmCtxRtCondition(&p->obj,cmSubSysFailRC,"%s failed because the state is EOL.",__FUNCTION__);
  3124. unsigned n = cmMin((*vnRef)*tbc, p->cur->n * p->typeByteCnt );
  3125. memcpy(v, p->cur->u.v, n );
  3126. *vnRef = n/tbc;
  3127. return cmOkRC;
  3128. }
  3129. cmRC_t _cmVectArrayReadMatrixV( cmCtx* ctx, const char* fn, void** mRef, unsigned* rnRef, unsigned* cnRef )
  3130. {
  3131. assert( mRef != NULL );
  3132. assert( cnRef != NULL );
  3133. assert( rnRef != NULL );
  3134. *mRef = NULL;
  3135. *cnRef = 0;
  3136. *rnRef = 0;
  3137. cmRC_t rc = cmOkRC;
  3138. cmVectArray_t* va;
  3139. if((va = cmVectArrayAllocFromFile(ctx, fn )) == NULL )
  3140. rc = cmCtxRtCondition(&ctx->obj,cmSubSysFailRC,"Unable to read the vectarray from the file '%s'.", cmStringNullGuard(fn));
  3141. else
  3142. {
  3143. unsigned rn = cmVectArrayCount(va); // count of rows
  3144. unsigned cn = cmVectArrayMaxRowCount(va); // max count of ele's among all rows
  3145. char* m = cmMemAllocZ(char,va->typeByteCnt*rn*cn); // allocate the matrix
  3146. unsigned ci = 0;
  3147. cmVectArrayRewind(va);
  3148. // read each vector into a column of m[]
  3149. for(; !cmVectArrayIsEOL(va); ++ci)
  3150. {
  3151. unsigned n = cmVectArrayEleCount(va);
  3152. assert( m+(ci*rn+n)*va->typeByteCnt <= m + rn*cn*va->typeByteCnt );
  3153. if( _cmVectArrayGetV(va, m + ci*rn*va->typeByteCnt, &n, va->typeByteCnt) != cmOkRC )
  3154. goto errLabel;
  3155. cmVectArrayAdvance(va,1);
  3156. }
  3157. *mRef = m;
  3158. *cnRef = cn;
  3159. *rnRef = rn;
  3160. }
  3161. errLabel:
  3162. if( va != NULL )
  3163. cmVectArrayFree(&va);
  3164. return rc;
  3165. }
  3166. cmRC_t cmVectArrayReadMatrixV( cmCtx* ctx, const char* fn, void** mRef, unsigned* rnRef, unsigned* cnRef )
  3167. { return _cmVectArrayReadMatrixV(ctx, fn, mRef, rnRef, cnRef ); }
  3168. cmRC_t cmVectArrayReadMatrixS( cmCtx* ctx, const char* fn, cmSample_t** mRef, unsigned* rnRef, unsigned* cnRef )
  3169. { return _cmVectArrayReadMatrixV(ctx, fn, (void**)mRef, rnRef, cnRef ); }
  3170. cmRC_t cmVectArrayReadMatrixR( cmCtx* ctx, const char* fn, cmReal_t** mRef, unsigned* rnRef, unsigned* cnRef )
  3171. { return _cmVectArrayReadMatrixV(ctx, fn, (void**)mRef, rnRef, cnRef ); }
  3172. cmRC_t cmVectArrayReadMatrixD( cmCtx* ctx, const char* fn, double** mRef, unsigned* rnRef, unsigned* cnRef )
  3173. { return _cmVectArrayReadMatrixV(ctx, fn, (void**)mRef, rnRef, cnRef ); }
  3174. cmRC_t cmVectArrayReadMatrixF( cmCtx* ctx, const char* fn, float** mRef, unsigned* rnRef, unsigned* cnRef )
  3175. { return _cmVectArrayReadMatrixV(ctx, fn, (void**)mRef, rnRef, cnRef ); }
  3176. cmRC_t cmVectArrayReadMatrixI( cmCtx* ctx, const char* fn, int** mRef, unsigned* rnRef, unsigned* cnRef )
  3177. { return _cmVectArrayReadMatrixV(ctx, fn, (void**)mRef, rnRef, cnRef ); }
  3178. cmRC_t cmVectArrayReadMatrixU( cmCtx* ctx, const char* fn, unsigned** mRef, unsigned* rnRef, unsigned* cnRef )
  3179. { return _cmVectArrayReadMatrixV(ctx, fn, (void**)mRef, rnRef, cnRef ); }
  3180. cmRC_t cmVectArrayForEachTextFuncS( void* arg, unsigned idx, const cmSample_t* xV, unsigned xN )
  3181. {
  3182. assert(0);
  3183. return cmOkRC;
  3184. }
  3185. cmRC_t cmVectArrayRewind( cmVectArray_t* p )
  3186. {
  3187. p->cur = p->bp;
  3188. return cmOkRC;
  3189. }
  3190. cmRC_t cmVectArrayAdvance( cmVectArray_t* p, unsigned n )
  3191. {
  3192. unsigned i;
  3193. for(i=0; i<n; ++i)
  3194. {
  3195. if( p->cur == NULL )
  3196. break;
  3197. p->cur = p->cur->link;
  3198. }
  3199. return cmOkRC;
  3200. }
  3201. bool cmVectArrayIsEOL( const cmVectArray_t* p )
  3202. { return p->cur == NULL; }
  3203. unsigned cmVectArrayEleCount( const cmVectArray_t* p )
  3204. {
  3205. if( p->cur == NULL )
  3206. return 0;
  3207. return p->cur->n;
  3208. }
  3209. cmRC_t cmVectArrayGetV( cmVectArray_t* p, void* v, unsigned* vnRef )
  3210. { return _cmVectArrayGetV(p,v,vnRef,_cmVectArrayTypeByteCnt(p,p->flags)); }
  3211. cmRC_t cmVectArrayGetS( cmVectArray_t* p, cmSample_t* v, unsigned* vnRef )
  3212. {
  3213. assert( cmIsFlag(p->flags,kSampleVaFl) );
  3214. return _cmVectArrayGetV(p,v,vnRef,sizeof(cmSample_t));
  3215. }
  3216. cmRC_t cmVectArrayGetR( cmVectArray_t* p, cmReal_t* v, unsigned* vnRef )
  3217. {
  3218. assert( cmIsFlag(p->flags,kRealVaFl) );
  3219. return _cmVectArrayGetV(p,v,vnRef,sizeof(cmReal_t));
  3220. }
  3221. cmRC_t cmVectArrayGetD( cmVectArray_t* p, double* v, unsigned* vnRef )
  3222. {
  3223. assert( cmIsFlag(p->flags,kDoubleVaFl) );
  3224. return _cmVectArrayGetV(p,v,vnRef,sizeof(double));
  3225. }
  3226. cmRC_t cmVectArrayGetF( cmVectArray_t* p, float* v, unsigned* vnRef )
  3227. {
  3228. assert( cmIsFlag(p->flags,kFloatVaFl) );
  3229. return _cmVectArrayGetV(p,v,vnRef,sizeof(float));
  3230. }
  3231. cmRC_t cmVectArrayGetI( cmVectArray_t* p, int* v, unsigned* vnRef )
  3232. {
  3233. assert( cmIsFlag(p->flags,kIntVaFl) );
  3234. return _cmVectArrayGetV(p,v,vnRef,sizeof(int));
  3235. }
  3236. cmRC_t cmVectArrayGetU( cmVectArray_t* p, unsigned* v, unsigned* vnRef )
  3237. {
  3238. assert( cmIsFlag(p->flags,kUIntVaFl) );
  3239. return _cmVectArrayGetV(p,v,vnRef,sizeof(unsigned));
  3240. }
  3241. cmRC_t _cmVectArrayMatrixIsEqual( cmCtx* ctx, const char* fn, const void* mm, unsigned rn, unsigned cn, unsigned flags, bool* resultFlRef )
  3242. {
  3243. assert( resultFlRef != NULL );
  3244. cmRC_t rc = cmOkRC;
  3245. cmVectArray_t* p = NULL;
  3246. const char* m = (const char*)mm;
  3247. unsigned tbc = _cmVectArrayTypeByteCnt(NULL,flags);
  3248. unsigned ri = 0;
  3249. char* vv = cmMemAlloc(char,cn*tbc);
  3250. *resultFlRef = false;
  3251. // read the vector array
  3252. if((p = cmVectArrayAllocFromFile(ctx, fn )) == NULL)
  3253. {
  3254. rc = cmCtxRtCondition(&ctx->obj,cmSubSysFailRC,"Unable to read the VectArray from the file '%s'.", cmStringNullGuard(fn));
  3255. goto errLabel;
  3256. }
  3257. // verify that the matrix type matches the vector array type
  3258. if( (p->flags & kVaMask) != (flags & kVaMask) )
  3259. {
  3260. rc = cmCtxRtCondition(&ctx->obj,cmInvalidArgRC,"Invalid type conversion in '%s'.",__FUNCTION__);
  3261. goto errLabel;
  3262. }
  3263. // the row count of the VectArray and m[] must be the same
  3264. if( cmVectArrayCount(p) != rn )
  3265. {
  3266. *resultFlRef = false;
  3267. goto errLabel;
  3268. }
  3269. // for each row in VectArray
  3270. for(; !cmVectArrayIsEOL(p); ++ri )
  3271. {
  3272. unsigned vn = cmVectArrayEleCount(p);
  3273. char v[ vn*p->typeByteCnt ];
  3274. unsigned ci;
  3275. // get the current row from the VectArray into v[vn]
  3276. if( _cmVectArrayGetV(p,v,&vn,p->typeByteCnt) != cmOkRC )
  3277. goto errLabel;
  3278. // if the size of the current row does not match the row element count of the matrix
  3279. if( vn != cn )
  3280. goto errLabel;
  3281. for(ci=0; ci<cn; ++ci)
  3282. memcpy(vv + ci*tbc, m + (ri*tbc) + (ci*rn*tbc), tbc );
  3283. // the current row does not match the matrix column vector
  3284. if( memcmp(v, vv, vn*p->typeByteCnt ) != 0 )
  3285. goto errLabel;
  3286. cmVectArrayAdvance(p,1);
  3287. }
  3288. *resultFlRef = true;
  3289. errLabel:
  3290. if( p != NULL )
  3291. cmVectArrayFree(&p);
  3292. cmMemFree(vv);
  3293. return rc;
  3294. }
  3295. cmRC_t cmVectArrayMatrixIsEqualV( cmCtx* ctx, const char* fn, const void* m, unsigned rn, unsigned cn, bool* resultFlRef, unsigned flags )
  3296. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, flags, resultFlRef); }
  3297. cmRC_t cmVectArrayMatrixIsEqualS( cmCtx* ctx, const char* fn, const cmSample_t* m, unsigned rn, unsigned cn, bool* resultFlRef )
  3298. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, kSampleVaFl, resultFlRef ); }
  3299. cmRC_t cmVectArrayMatrixIsEqualR( cmCtx* ctx, const char* fn, const cmReal_t* m, unsigned rn, unsigned cn, bool* resultFlRef )
  3300. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, kRealVaFl, resultFlRef ); }
  3301. cmRC_t cmVectArrayMatrixIsEqualD( cmCtx* ctx, const char* fn, const double* m, unsigned rn, unsigned cn, bool* resultFlRef )
  3302. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, kDoubleVaFl, resultFlRef ); }
  3303. cmRC_t cmVectArrayMatrixIsEqualF( cmCtx* ctx, const char* fn, const float* m, unsigned rn, unsigned cn, bool* resultFlRef )
  3304. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, kFloatVaFl, resultFlRef ); }
  3305. cmRC_t cmVectArrayMatrixIsEqualI( cmCtx* ctx, const char* fn, const int* m, unsigned rn, unsigned cn, bool* resultFlRef )
  3306. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, kIntVaFl, resultFlRef ); }
  3307. cmRC_t cmVectArrayMatrixIsEqualU( cmCtx* ctx, const char* fn, const unsigned* m, unsigned rn, unsigned cn, bool* resultFlRef )
  3308. { return _cmVectArrayMatrixIsEqual(ctx, fn, m, rn, cn, kUIntVaFl, resultFlRef ); }
  3309. unsigned cmVectArrayVectEleCount( cmVectArray_t* p, unsigned groupIdx, unsigned groupCnt )
  3310. {
  3311. unsigned n = 0;
  3312. cmVectArrayVect_t* pos = p->cur;
  3313. if( cmVectArrayRewind(p) != cmOkRC )
  3314. goto errLabel;
  3315. if( cmVectArrayAdvance(p,groupIdx) != cmOkRC )
  3316. goto errLabel;
  3317. while( !cmVectArrayIsEOL(p) )
  3318. {
  3319. n += cmVectArrayEleCount(p);
  3320. if(cmVectArrayAdvance(p,groupCnt) != cmOkRC )
  3321. goto errLabel;
  3322. }
  3323. errLabel:
  3324. p->cur = pos;
  3325. return n;
  3326. }
  3327. cmRC_t cmVectArrayFormVectF( cmVectArray_t* p, unsigned groupIdx, unsigned groupCnt, float** vRef, unsigned* vnRef )
  3328. {
  3329. cmRC_t rc = cmOkRC;
  3330. *vRef = NULL;
  3331. *vnRef = 0;
  3332. unsigned N = cmVectArrayVectEleCount(p,groupIdx,groupCnt);
  3333. if( N == 0 )
  3334. return rc;
  3335. float* v = cmMemAllocZ(float,N);
  3336. unsigned i = 0;
  3337. cmVectArrayVect_t* pos = p->cur;
  3338. if( cmVectArrayRewind(p) != cmOkRC )
  3339. goto errLabel;
  3340. if( cmVectArrayAdvance(p,groupIdx) != cmOkRC )
  3341. goto errLabel;
  3342. while( !cmVectArrayIsEOL(p) )
  3343. {
  3344. unsigned n = cmVectArrayEleCount(p);
  3345. assert(i+n <= N);
  3346. cmVectArrayGetF(p,v+i,&n);
  3347. i += n;
  3348. cmVectArrayAdvance(p,groupCnt);
  3349. }
  3350. *vRef = v;
  3351. *vnRef = i;
  3352. errLabel:
  3353. p->cur = pos;
  3354. return rc;
  3355. }
  3356. cmRC_t cmVectArrayFormVectColF( cmVectArray_t* p, unsigned groupIdx, unsigned groupCnt, unsigned colIdx, float** vRef, unsigned* vnRef )
  3357. {
  3358. cmRC_t rc = cmOkRC;
  3359. *vRef = NULL;
  3360. *vnRef = 0;
  3361. // assume there will be one output element for each group
  3362. unsigned N = cmVectArrayCount(p)/groupCnt + 1;
  3363. if( N == 0 )
  3364. return rc;
  3365. float* v = cmMemAllocZ(float,N);
  3366. unsigned i = 0;
  3367. cmVectArrayVect_t* pos = p->cur;
  3368. if( cmVectArrayRewind(p) != cmOkRC )
  3369. goto errLabel;
  3370. if( cmVectArrayAdvance(p,groupIdx) != cmOkRC )
  3371. goto errLabel;
  3372. while( i<N && !cmVectArrayIsEOL(p) )
  3373. {
  3374. unsigned tn = cmVectArrayEleCount(p);
  3375. float tv[tn];
  3376. // read the sub-vector
  3377. cmVectArrayGetF(p,tv,&tn);
  3378. // store the output value
  3379. if( colIdx < tn )
  3380. {
  3381. v[i] = tv[colIdx];
  3382. i += 1;
  3383. }
  3384. cmVectArrayAdvance(p,groupCnt);
  3385. }
  3386. *vRef = v;
  3387. *vnRef = i;
  3388. errLabel:
  3389. p->cur = pos;
  3390. return rc;
  3391. }
  3392. cmRC_t cmVectArrayFormVectColU( cmVectArray_t* p, unsigned groupIdx, unsigned groupCnt, unsigned colIdx, unsigned** vRef, unsigned* vnRef )
  3393. {
  3394. cmRC_t rc = cmOkRC;
  3395. *vRef = NULL;
  3396. *vnRef = 0;
  3397. // assume there will be one output element for each group
  3398. unsigned N = cmVectArrayCount(p)/groupCnt + 1;
  3399. if( N == 0 )
  3400. return rc;
  3401. unsigned* v = cmMemAllocZ(unsigned,N);
  3402. unsigned i = 0;
  3403. cmVectArrayVect_t* pos = p->cur;
  3404. if( cmVectArrayRewind(p) != cmOkRC )
  3405. goto errLabel;
  3406. if( cmVectArrayAdvance(p,groupIdx) != cmOkRC )
  3407. goto errLabel;
  3408. while( i<N && !cmVectArrayIsEOL(p) )
  3409. {
  3410. unsigned tn = cmVectArrayEleCount(p);
  3411. unsigned tv[tn];
  3412. // read the sub-vector
  3413. cmVectArrayGetU(p,tv,&tn);
  3414. assert( colIdx < tn );
  3415. // store the output value
  3416. if( colIdx < tn )
  3417. v[i++] = tv[colIdx];
  3418. cmVectArrayAdvance(p,groupCnt);
  3419. }
  3420. *vRef = v;
  3421. *vnRef = i;
  3422. errLabel:
  3423. p->cur = pos;
  3424. return rc;
  3425. }
  3426. cmRC_t cmVectArrayTest( cmCtx* ctx, const char* fn, bool genFl )
  3427. {
  3428. cmRC_t rc = cmOkRC;
  3429. cmVectArray_t* p = NULL;
  3430. if( fn == NULL || strlen(fn)==0 )
  3431. return cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Invalid test output file name.");
  3432. if( genFl )
  3433. {
  3434. unsigned flags = kSampleVaFl;
  3435. cmSample_t v[] = { 0, 1, 2, 3, 4, 5 };
  3436. if( (p = cmVectArrayAlloc(ctx,flags)) == NULL )
  3437. return cmCtxRtCondition(&p->obj,cmSubSysFailRC,"The vectory array object allocation failed.");
  3438. if( cmVectArrayAppendS(p,v,1) != cmOkRC )
  3439. {
  3440. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Vector append 1 failed.");
  3441. goto errLabel;
  3442. }
  3443. if( cmVectArrayAppendS(p,v+1,2) != cmOkRC )
  3444. {
  3445. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Vector append 2 failed.");
  3446. goto errLabel;
  3447. }
  3448. if( cmVectArrayAppendS(p,v+3,3) != cmOkRC )
  3449. {
  3450. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Vector append 3 failed.");
  3451. goto errLabel;
  3452. }
  3453. if( cmVectArrayWrite(p,fn) != cmOkRC )
  3454. {
  3455. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"Vector array write failed.");
  3456. goto errLabel;
  3457. }
  3458. //cmVectArrayForEachS(p,0,cmVectArrayEleCount(p),cmVectArrayForEachTextFuncS,&ctx->printRpt);
  3459. //if( cmVectArrayFree(&p) != cmOkRC )
  3460. //{
  3461. // rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"The vectory array release failed.");
  3462. // goto errLabel;
  3463. //}
  3464. }
  3465. else
  3466. {
  3467. if((p = cmVectArrayAllocFromFile(ctx, fn )) == NULL )
  3468. {
  3469. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"VectArray alloc from file failed.");
  3470. goto errLabel;
  3471. }
  3472. while(!cmVectArrayIsEOL(p))
  3473. {
  3474. unsigned n = cmVectArrayEleCount(p);
  3475. cmSample_t v[n];
  3476. if( cmVectArrayGetS(p,v,&n) != cmOkRC )
  3477. {
  3478. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"VectArrayGetS() failed.");
  3479. goto errLabel;
  3480. }
  3481. //cmVOS_PrintL("v:",NULL,1,n,v);
  3482. cmVectArrayAdvance(p,1);
  3483. }
  3484. // Test matrix reading
  3485. cmSample_t* m;
  3486. unsigned rn,cn;
  3487. if( cmVectArrayReadMatrixS(ctx, fn, &m, &rn, &cn ) != cmOkRC )
  3488. goto errLabel;
  3489. else
  3490. {
  3491. //cmVOS_PrintL("v:",NULL,rn,cn,m);
  3492. cmMemFree(m);
  3493. }
  3494. }
  3495. errLabel:
  3496. if( cmVectArrayFree(&p) != cmOkRC )
  3497. rc = cmCtxRtCondition(&p->obj,cmSubSysFailRC,"The vector array release failed.");
  3498. return rc;
  3499. }
  3500. //-----------------------------------------------------------------------------------------------------------------------
  3501. cmWhFilt* cmWhFiltAlloc( cmCtx* c, cmWhFilt* p, unsigned binCnt, cmReal_t binHz, cmReal_t coeff, cmReal_t maxHz )
  3502. {
  3503. cmWhFilt* op = cmObjAlloc(cmWhFilt,c,p);
  3504. if( binCnt > 0 )
  3505. if( cmWhFiltInit(op,binCnt,binHz,coeff,maxHz) != cmOkRC )
  3506. cmWhFiltFree(&op);
  3507. return op;
  3508. }
  3509. cmRC_t cmWhFiltFree( cmWhFilt** pp )
  3510. {
  3511. cmRC_t rc = cmOkRC;
  3512. if( pp==NULL || *pp==NULL )
  3513. return rc;
  3514. cmWhFilt* p = *pp;
  3515. if((rc = cmWhFiltFinal(p)) != cmOkRC )
  3516. return rc;
  3517. cmMemFree(p->whM);
  3518. cmMemFree(p->whiV);
  3519. cmMemFree(p->iV);
  3520. cmObjFree(pp);
  3521. return rc;
  3522. }
  3523. cmRC_t cmWhFiltInit( cmWhFilt* p, unsigned binCnt, cmReal_t binHz, cmReal_t coeff, cmReal_t maxHz )
  3524. {
  3525. cmRC_t rc;
  3526. if((rc = cmWhFiltFinal(p)) != cmOkRC )
  3527. return rc;
  3528. p->binCnt = binCnt;
  3529. p->binHz = binHz;
  3530. p->bandCnt = maxHz == 0 ? 34 : ceil(log10(maxHz/229.0 + 1) * 21.4 - 1)-1;
  3531. if( p->bandCnt <= 0 )
  3532. return cmCtxRtCondition(&p->obj, cmInvalidArgRC, "Max. Hz too low to form any frequency bands.");
  3533. cmReal_t flV[ p->bandCnt ];
  3534. cmReal_t fcV[ p->bandCnt ];
  3535. cmReal_t fhV[ p->bandCnt ];
  3536. int i;
  3537. for(i=0; i<p->bandCnt; ++i)
  3538. {
  3539. fcV[i] = 229.0 * (pow(10.0,(i+2)/21.4) - 1.0);
  3540. flV[i] = i==0 ? 0 : fcV[i-1];
  3541. }
  3542. for(i=0; i<p->bandCnt-1; ++i)
  3543. fhV[i] = fcV[i+1];
  3544. fhV[p->bandCnt-1] = fcV[p->bandCnt-1] + (fcV[p->bandCnt-1] - fcV[p->bandCnt-2]);
  3545. //cmVOR_PrintL("flV",NULL,1,p->bandCnt,flV);
  3546. //cmVOR_PrintL("fcV",NULL,1,p->bandCnt,fcV);
  3547. //cmVOR_PrintL("fhV",NULL,1,p->bandCnt,fhV);
  3548. cmReal_t* tM = cmMemAlloc(cmReal_t,p->bandCnt * p->binCnt);
  3549. p->whM = cmMemResizeZ(cmReal_t,p->whM,p->binCnt * p->bandCnt);
  3550. p->iV = cmMemResizeZ(cmReal_t,p->iV,p->binCnt);
  3551. // generate the bin index values
  3552. for(i=0; i<p->binCnt; ++i)
  3553. p->iV[i] = i;
  3554. cmReal_t stSpread = 0; // set stSpread to 0 to use flV/fhV[]
  3555. cmVOR_TriangleMask(tM, p->bandCnt, p->binCnt, fcV, p->binHz, stSpread, flV, fhV );
  3556. cmVOR_Transpose(p->whM, tM, p->bandCnt, p->binCnt );
  3557. cmMemFree(tM);
  3558. //cmVOR_PrintL("whM",NULL,p->bandCnt,p->binCnt,p->whM);
  3559. //cmVectArrayWriteMatrixR(p->obj.ctx, "/home/kevin/temp/frqtrk/whM.va", p->whM, p->binCnt, p->bandCnt );
  3560. unsigned whiN = p->bandCnt+2;
  3561. p->whiV = cmMemResizeZ(cmReal_t,p->whiV,whiN);
  3562. for(i=0; i<whiN; ++i)
  3563. {
  3564. if( i == 0 )
  3565. p->whiV[i] = 0;
  3566. else
  3567. if( i == whiN-1 )
  3568. p->whiV[i] = fhV[p->bandCnt-1]/binHz;
  3569. else
  3570. p->whiV[i] = fcV[i-1]/binHz;
  3571. }
  3572. //cmVOR_PrintL("whiV",NULL,1,whiN,p->whiV);
  3573. //cmVectArrayWriteMatrixR(p->obj.ctx, "/home/kevin/temp/frqtrk/whiV.va", p->whiV, whiN, 1 );
  3574. return rc;
  3575. }
  3576. cmRC_t cmWhFiltFinal( cmWhFilt* p )
  3577. { return cmOkRC; }
  3578. cmRC_t cmWhFiltExec( cmWhFilt* p, const cmReal_t* xV, cmReal_t* yV, unsigned xyN )
  3579. {
  3580. assert( xyN == p->binCnt);
  3581. cmRC_t rc = cmOkRC;
  3582. unsigned whiN = p->bandCnt + 2;
  3583. unsigned mbi = cmMin(xyN, floor(p->whiV[whiN-1]));
  3584. // calculate the level in each band to form a composite filter
  3585. cmReal_t y0V[ whiN ];
  3586. cmReal_t* b0V = y0V + 1;
  3587. cmVOR_MultVVM(b0V, p->bandCnt, xV, p->binCnt, p->whM );
  3588. //cmVOR_PrintL("b0V",NULL,1,p->bandCnt,b0V);
  3589. // BEWARE: zeros in b0V will generate Inf's when sent
  3590. // through the cmVOR_PowVS() function.
  3591. int i;
  3592. for(i=0; i<p->bandCnt; ++i)
  3593. if( b0V[i] < 0.000001 )
  3594. b0V[i] = 0.000001;
  3595. // apply a non-linear expansion function to each band
  3596. cmVOR_PowVS(b0V,p->bandCnt,p->coeff-1);
  3597. //cmVOR_PrintL("b0V",NULL,1,p->bandCnt,b0V);
  3598. // add edge values to the filter
  3599. y0V[0] = b0V[0];
  3600. y0V[whiN-1] = b0V[p->bandCnt-1];
  3601. //cmVOR_PrintL("y0V",NULL,1,whiN,y0V);
  3602. cmVOR_Interp1(yV,p->iV,p->binCnt,p->whiV,y0V,whiN);
  3603. cmVOR_Fill(yV+mbi,xyN-mbi,1.0);
  3604. //cmVOR_PrintL("yV",NULL,1,p->binCnt,yV);
  3605. cmVOR_MultVV(yV,xyN,xV);
  3606. return rc;
  3607. }
  3608. //-----------------------------------------------------------------------------------------------------------------------
  3609. cmFrqTrk* cmFrqTrkAlloc( cmCtx* c, cmFrqTrk* p, const cmFrqTrkArgs_t* a )
  3610. {
  3611. cmFrqTrk* op = cmObjAlloc(cmFrqTrk,c,p);
  3612. op->logVa = cmVectArrayAlloc(c,kRealVaFl);
  3613. op->levelVa = cmVectArrayAlloc(c,kRealVaFl);
  3614. op->specVa = cmVectArrayAlloc(c,kRealVaFl);
  3615. op->attenVa = cmVectArrayAlloc(c,kRealVaFl);
  3616. op->wf = cmWhFiltAlloc(c,NULL,0,0,0,0);
  3617. if( a != NULL )
  3618. if( cmFrqTrkInit(op,a) != cmOkRC )
  3619. cmFrqTrkFree(&op);
  3620. return op;
  3621. }
  3622. cmRC_t cmFrqTrkFree( cmFrqTrk** pp )
  3623. {
  3624. cmRC_t rc = cmOkRC;
  3625. if( pp==NULL || *pp==NULL )
  3626. return rc;
  3627. cmFrqTrk* p = *pp;
  3628. if((rc = cmFrqTrkFinal(p)) != cmOkRC )
  3629. return rc;
  3630. unsigned i;
  3631. for(i=0; i<p->a.chCnt; ++i)
  3632. {
  3633. cmMemFree(p->ch[i].dbV);
  3634. cmMemFree(p->ch[i].hzV);
  3635. }
  3636. cmMemFree(p->ch);
  3637. cmMemFree(p->dbM);
  3638. cmMemFree(p->pkiV);
  3639. cmMemFree(p->dbV);
  3640. cmMemFree(p->aV);
  3641. cmVectArrayFree(&p->logVa);
  3642. cmVectArrayFree(&p->levelVa);
  3643. cmVectArrayFree(&p->specVa);
  3644. cmVectArrayFree(&p->attenVa);
  3645. cmWhFiltFree(&p->wf);
  3646. cmMemFree(p->logFn);
  3647. cmMemFree(p->levelFn);
  3648. cmMemFree(p->specFn);
  3649. cmMemFree(p->attenFn);
  3650. cmObjFree(pp);
  3651. return rc;
  3652. }
  3653. cmRC_t cmFrqTrkInit( cmFrqTrk* p, const cmFrqTrkArgs_t* a )
  3654. {
  3655. cmRC_t rc;
  3656. if((rc = cmFrqTrkFinal(p)) != cmOkRC )
  3657. return rc;
  3658. p->a = *a;
  3659. p->ch = cmMemResizeZ(cmFrqTrkCh_t,p->ch,a->chCnt );
  3660. p->hN = cmMax(1,a->wndSecs * a->srate / a->hopSmpCnt );
  3661. p->sN = 4*p->hN;
  3662. p->binHz = a->srate / ((p->a.binCnt-1)*2);
  3663. p->bN = cmMin( p->a.binCnt, ceil(p->a.pkMaxHz / p->binHz ));
  3664. p->dbM = cmMemResizeZ(cmReal_t,p->dbM,p->hN*p->bN);
  3665. p->hi = 0;
  3666. p->fN = 0;
  3667. p->dbV = cmMemResizeZ(cmReal_t,p->dbV,p->bN);
  3668. p->pkiV = cmMemResizeZ(unsigned,p->pkiV,p->bN);
  3669. p->deadN_max = a->maxTrkDeadSec * a->srate / a->hopSmpCnt;
  3670. p->minTrkN = a->minTrkSec * a->srate / a->hopSmpCnt;
  3671. p->nextTrkId = 1;
  3672. p->aV = cmMemResizeZ(cmReal_t,p->aV,p->a.binCnt);
  3673. p->attenDlyPhsMax = cmMax(3,a->attenDlySec * a->srate / a->hopSmpCnt );
  3674. p->attenPhsMax = cmMax(3,a->attenAtkSec * a->srate / a->hopSmpCnt );
  3675. if( a->logFn != NULL )
  3676. p->logFn = cmMemResizeStr(p->logFn,a->logFn);
  3677. if( a->levelFn != NULL )
  3678. p->levelFn = cmMemResizeStr(p->levelFn,a->levelFn);
  3679. if( a->specFn != NULL )
  3680. p->specFn = cmMemResizeStr(p->specFn,a->specFn);
  3681. if( a->attenFn != NULL )
  3682. p->attenFn = cmMemResizeStr(p->attenFn,a->attenFn);
  3683. if(cmWhFiltInit(p->wf,p->bN,p->binHz,p->a.whFiltCoeff,p->a.pkMaxHz) != cmOkRC )
  3684. cmCtxRtCondition(&p->obj, cmSubSysFailRC, "Whitening filter intitialization failed.");
  3685. unsigned i;
  3686. for(i=0; i<p->a.chCnt; ++i)
  3687. {
  3688. p->ch[i].dbV = cmMemResizeZ(cmReal_t,p->ch[i].dbV,p->sN);
  3689. p->ch[i].hzV = cmMemResizeZ(cmReal_t,p->ch[i].hzV,p->sN);
  3690. }
  3691. return rc;
  3692. }
  3693. cmRC_t cmFrqTrkFinal( cmFrqTrk* p )
  3694. {
  3695. cmRC_t rc = cmOkRC;
  3696. if( p->logFn != NULL )
  3697. cmVectArrayWrite(p->logVa,p->logFn);
  3698. if( p->levelFn != NULL )
  3699. cmVectArrayWrite(p->levelVa,p->levelFn);
  3700. if( p->specFn != NULL )
  3701. cmVectArrayWrite(p->specVa,p->specFn);
  3702. if( p->attenFn != NULL )
  3703. cmVectArrayWrite(p->attenVa,p->attenFn);
  3704. cmWhFiltFinal(p->wf);
  3705. return rc;
  3706. }
  3707. // Return an available channel record or NULL if all channel records are in use.
  3708. cmFrqTrkCh_t* _cmFrqTrkFindAvailCh( cmFrqTrk* p )
  3709. {
  3710. unsigned i;
  3711. for(i=0; i<p->a.chCnt; ++i)
  3712. if( p->ch[i].activeFl == false )
  3713. return p->ch + i;
  3714. return NULL;
  3715. }
  3716. // Estimate the peak frequency by parabolic interpolotion into hzV[p->bN]
  3717. void _cmFrqTrkMagnToHz( cmFrqTrk* p, const cmReal_t* dbV, unsigned* pkiV, unsigned pkN, cmReal_t* hzV )
  3718. {
  3719. unsigned i;
  3720. for(i=0; i<pkN; ++i)
  3721. if( pkiV[i] != cmInvalidIdx )
  3722. {
  3723. unsigned pki = pkiV[i];
  3724. cmReal_t y0 = pki>0 ? dbV[ pki-1 ] : dbV[pki];
  3725. cmReal_t y1 = dbV[ pki ];
  3726. cmReal_t y2 = pki<p->bN-1 ? dbV[ pki+1 ] : dbV[pki];
  3727. cmReal_t den = y0 - (2.*y1) + y2;
  3728. cmReal_t offs = den==0 ? 0 : 0.5 * ((y0 - y2) / den);
  3729. hzV[pki] = p->binHz * (pki+offs);
  3730. //if( hzV[pki] < 0 )
  3731. //{
  3732. // printf("%f : %f %f %f : %f %f\n",hzV[pki],y0,y1,y2,den,offs);
  3733. //}
  3734. }
  3735. }
  3736. unsigned _cmFrqTrkActiveChCount( cmFrqTrk* p )
  3737. {
  3738. unsigned n = 0;
  3739. unsigned i;
  3740. for(i=0; i<p->a.chCnt; ++i)
  3741. if( p->ch[i].activeFl )
  3742. ++n;
  3743. return n;
  3744. }
  3745. void _cmFrqTrkWriteLevel( cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, unsigned bN )
  3746. {
  3747. if( p->levelFn != NULL )
  3748. {
  3749. double maxHz = 5000.0;
  3750. unsigned maxBinIdx = cmMin(bN,maxHz / p->binHz);
  3751. unsigned vn = 3;
  3752. cmReal_t v[vn];
  3753. unsigned idx = cmVOR_MaxIndex(dbV,maxBinIdx,1);
  3754. v[0] = cmVOR_Mean(dbV,maxBinIdx);
  3755. v[1] = dbV[idx];
  3756. v[2] = hzV[idx];
  3757. cmVectArrayAppendR(p->levelVa,v,vn);
  3758. }
  3759. }
  3760. void _cmFrqTrkWriteLog( cmFrqTrk* p )
  3761. {
  3762. unsigned n;
  3763. cmReal_t* vb = NULL;
  3764. if( p->logFn == NULL )
  3765. return;
  3766. if((n = _cmFrqTrkActiveChCount(p)) > 0 )
  3767. {
  3768. unsigned i,j;
  3769. // sn = count of elements in the summary sub-vector
  3770. unsigned sn = 3;
  3771. // each active channel will emit 7 values
  3772. unsigned nn = 1 + n*7 + sn;
  3773. // allocate the row vector
  3774. vb = cmMemResize(cmReal_t,vb,nn);
  3775. // row format
  3776. // [ nn idV[n] hzV[n] ... hsV[n] smV[sn] ]
  3777. // n = (nn - (1 + sn)) / 7
  3778. *vb = nn; // the first element in the vector contains the length of the row
  3779. cmReal_t* v = vb + 1;
  3780. // setup the base pointer to each sub-vector
  3781. cmReal_t* idV = v + n * 0;
  3782. cmReal_t* hzV = v + n * 1;
  3783. cmReal_t* dbV = v + n * 2;
  3784. cmReal_t* stV = v + n * 3;
  3785. cmReal_t* dsV = v + n * 4;
  3786. cmReal_t* hsV = v + n * 5;
  3787. cmReal_t* agV = v + n * 6;
  3788. cmReal_t* smV = v + n * 7; // summary information
  3789. smV[0] = p->newTrkCnt;
  3790. smV[1] = p->curTrkCnt;
  3791. smV[2] = p->deadTrkCnt;
  3792. // for each active channel
  3793. for(i=0,j=0; i<p->a.chCnt; ++i)
  3794. if( p->ch[i].activeFl )
  3795. {
  3796. assert(j < n);
  3797. // elements of each sub-vector associated with a given
  3798. // index refer to the same track record - element i therefore
  3799. // refers to active track index i.
  3800. idV[j] = p->ch[i].id;
  3801. hzV[j] = p->ch[i].hz;
  3802. dbV[j] = p->ch[i].db;
  3803. stV[j] = p->ch[i].dN;
  3804. dsV[j] = p->ch[i].db_std;
  3805. hsV[j] = p->ch[i].hz_std;
  3806. agV[j] = p->ch[i].attenGain;
  3807. ++j;
  3808. }
  3809. cmVectArrayAppendR(p->logVa, vb, nn );
  3810. }
  3811. cmMemFree(vb);
  3812. }
  3813. void _cmFrqTrkPrintChs( const cmFrqTrk* p )
  3814. {
  3815. unsigned i;
  3816. for(i=0; i<p->a.chCnt; ++i)
  3817. {
  3818. cmFrqTrkCh_t* c = p->ch + i;
  3819. printf("%i : %i tN:%i hz:%f db:%f\n",i,c->activeFl,c->tN,c->hz,c->db);
  3820. }
  3821. }
  3822. // Used to sort the channels into descending dB order.
  3823. int _cmFrqTrkChCompare( const void* p0, const void* p1 )
  3824. { return ((cmFrqTrkCh_t*)p0)->db - ((cmFrqTrkCh_t*)p1)->db; }
  3825. // Return the index of the peak associated with pkiV[i] which best matches the tracker 'c'
  3826. // or cmInvalidIdx if no valid peaks were found.
  3827. // pkiV[ pkN ] holds the indexes into dbV[] and hzV[] which are peaks.
  3828. // Some elements of pkiV[] may be set to cmInvalidIdx if the associated peak has already
  3829. // been selected by another tracker.
  3830. unsigned _cmFrqTrkFindPeak( cmFrqTrk* p, const cmFrqTrkCh_t* c, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
  3831. {
  3832. unsigned i,pki;
  3833. cmReal_t d_max = p->a.pkThreshDb;
  3834. unsigned d_idx = cmInvalidIdx;
  3835. cmReal_t hz_min = c->hz * pow(2,-p->a.stRange/12.0);
  3836. cmReal_t hz_max = c->hz * pow(2, p->a.stRange/12.0);
  3837. // find the peak with the most energy inside the frequency range hz_min to hz_max.
  3838. for(i=0; i<pkN; ++i)
  3839. if( ((pki = pkiV[i]) != cmInvalidIdx) && hz_min <= hzV[pki] && hzV[pki] <= hz_max && dbV[pki]>d_max )
  3840. {
  3841. d_max= dbV[pki];
  3842. d_idx = i;
  3843. }
  3844. return d_idx;
  3845. }
  3846. void _cmFrqTrkScoreChs( cmFrqTrk* p )
  3847. {
  3848. unsigned i;
  3849. for(i=0; i<p->a.chCnt; ++i)
  3850. if( p->ch[i].activeFl )
  3851. {
  3852. cmFrqTrkCh_t* c = p->ch + i;
  3853. c->dbV[ c->si ] = c->db;
  3854. c->hzV[ c->si ] = c->hz;
  3855. c->si = (c->si + 1) % p->sN;
  3856. c->sn += 1;
  3857. unsigned n = cmMin(c->sn,p->sN);
  3858. c->db_mean = cmVOR_Mean(c->dbV,n);
  3859. c->db_std = sqrt(cmVOR_Variance( c->dbV,n,&c->db_mean));
  3860. c->hz_mean = cmVOR_Mean(c->hzV,n);
  3861. c->hz_std = sqrt(cmVOR_Variance( c->hzV,n,&c->hz_mean));
  3862. //c->score = c->db / ((cmMax(0.1,c->db_std) + cmMax(0.1,c->hz_std))/2);
  3863. c->score = c->db - (c->db_std * 5) - (c->hz_std/50);
  3864. //printf("%f %f %f %f %f\n",c->db,cmMin(0.1,c->db_std),c->hz,cmMin(0.1,c->hz_std),c->score);
  3865. }
  3866. }
  3867. // Generate a filter that is wider for higher frequencies than lower frequencies.
  3868. unsigned _cmFrqTrkFillMap( cmFrqTrk* p, cmReal_t* map, unsigned maxN, cmReal_t hz )
  3869. {
  3870. assert( maxN % 2 == 1 );
  3871. unsigned i;
  3872. cmReal_t maxHz = p->a.srate/2;
  3873. unsigned mapN = cmMin(maxN,ceil(hz/maxHz * maxN));
  3874. if( mapN % 2 == 0 )
  3875. mapN += 1;
  3876. mapN = cmMin(maxN,mapN);
  3877. unsigned N = floor(mapN/2);
  3878. double COEFF = 0.3;
  3879. for(i=0; i<N; ++i)
  3880. {
  3881. map[i] = pow(((double)i+1)/(N+1),COEFF);
  3882. map[mapN-(i+1)] = map[i];
  3883. }
  3884. map[N] = 1.0;
  3885. return mapN;
  3886. }
  3887. void _cmFrqTrkApplyAtten( cmFrqTrk* p, cmReal_t* aV, cmReal_t gain, cmReal_t hz )
  3888. {
  3889. int cbi = cmMin(p->a.binCnt,cmMax(0,round(hz/p->binHz)));
  3890. //cmReal_t map[] = { .25, .5, 1, .5, .25 };
  3891. //int mapN = sizeof(map)/sizeof(map[0]);
  3892. unsigned maxN = 30; // must be odd
  3893. cmReal_t map[ maxN ];
  3894. int mapN = _cmFrqTrkFillMap(p, map, maxN, hz );
  3895. int j;
  3896. int ai = cbi - mapN/2;
  3897. for(j=0; j<mapN; ++j,++ai)
  3898. if( 0 <= ai && ai < p->a.binCnt )
  3899. aV[ai] *= 1.0 - (map[j] * gain);
  3900. }
  3901. void _cmFrqTrkUpdateFilter( cmFrqTrk* p )
  3902. {
  3903. unsigned i;
  3904. cmVOR_Fill(p->aV,p->a.binCnt,1.0);
  3905. for(i=0; i<p->a.chCnt; ++i)
  3906. if( p->ch[i].activeFl )
  3907. {
  3908. cmFrqTrkCh_t* c = p->ch + i;
  3909. //
  3910. if( c->score >= p->a.attenThresh && c->state == kNoStateFrqTrkId )
  3911. {
  3912. //printf("%f\n",c->score);
  3913. c->attenPhsIdx = 0;
  3914. c->state = kDlyFrqTrkId;
  3915. }
  3916. switch( c->state )
  3917. {
  3918. case kNoStateFrqTrkId:
  3919. break;
  3920. case kDlyFrqTrkId:
  3921. c->attenPhsIdx += 1;
  3922. if( c->attenPhsIdx >= p->attenDlyPhsMax && c->dN == 0 )
  3923. c->state = kAtkFrqTrkId;
  3924. break;
  3925. case kAtkFrqTrkId:
  3926. if( c->attenPhsIdx < p->attenDlyPhsMax + p->attenPhsMax )
  3927. {
  3928. c->attenGain = cmMin(1.0,p->a.attenGain * c->attenPhsIdx / p->attenPhsMax);
  3929. _cmFrqTrkApplyAtten(p, p->aV, c->attenGain, c->hz);
  3930. }
  3931. c->attenPhsIdx += 1;
  3932. if( c->attenPhsIdx >= p->attenDlyPhsMax + p->attenPhsMax )
  3933. c->state = kSusFrqTrkId;
  3934. break;
  3935. case kSusFrqTrkId:
  3936. if( c->dN > 0 )
  3937. {
  3938. if( c->attenPhsIdx > 0 )
  3939. {
  3940. c->attenPhsIdx -= 1;
  3941. c->attenGain = cmMin(1.0,p->a.attenGain * c->attenPhsIdx / p->attenPhsMax);
  3942. }
  3943. }
  3944. _cmFrqTrkApplyAtten(p,p->aV, c->attenGain, c->hz);
  3945. if( c->dN >= p->deadN_max )
  3946. c->state = kDcyFrqTrkId;
  3947. break;
  3948. case kDcyFrqTrkId:
  3949. if( c->attenPhsIdx > 0 )
  3950. {
  3951. c->attenPhsIdx -= 1;
  3952. c->attenGain = cmMin(1.0,p->a.attenGain * c->attenPhsIdx / p->attenPhsMax);
  3953. _cmFrqTrkApplyAtten(p,p->aV, c->attenGain, c->hz);
  3954. }
  3955. if( c->attenPhsIdx == 0 )
  3956. c->activeFl = false;
  3957. break;
  3958. }
  3959. }
  3960. }
  3961. // Extend the existing trackers
  3962. void _cmFrqTrkExtendChs( cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
  3963. {
  3964. unsigned i;
  3965. p->curTrkCnt = 0;
  3966. p->deadTrkCnt = 0;
  3967. // sort the channels in descending order
  3968. qsort(p->ch,p->a.chCnt,sizeof(cmFrqTrkCh_t),_cmFrqTrkChCompare);
  3969. // for each active channel
  3970. for(i=0; i<p->a.chCnt; ++i)
  3971. {
  3972. cmFrqTrkCh_t* c = p->ch + i;
  3973. if( c->activeFl )
  3974. {
  3975. unsigned pki;
  3976. // find the best peak to extend tracker 'c'.
  3977. if((pki = _cmFrqTrkFindPeak(p,c,dbV,hzV,pkiV,pkN)) == cmInvalidIdx )
  3978. {
  3979. // no valid track was found to extend tracker 'c'
  3980. c->dN += 1;
  3981. c->tN += 1;
  3982. if( c->dN >= p->deadN_max )
  3983. {
  3984. if( c->attenPhsIdx == 0 )
  3985. c->activeFl = false;
  3986. p->deadTrkCnt += 1;
  3987. }
  3988. }
  3989. else // ... update the tracker using the matching peak
  3990. {
  3991. unsigned j = pkiV[pki];
  3992. c->dN = 0;
  3993. c->db = dbV[ j ];
  3994. c->hz = hzV[ j ];
  3995. c->tN += 1;
  3996. pkiV[pki] = cmInvalidIdx; // mark the peak as unavailable.
  3997. p->curTrkCnt += 1;
  3998. }
  3999. }
  4000. }
  4001. }
  4002. // disable peaks which are within 'stRange' semitones of the frequency of active trackers.
  4003. void _cmFrqTrkDisableClosePeaks( cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
  4004. {
  4005. unsigned i;
  4006. for(i=0; i<p->a.chCnt; ++i)
  4007. {
  4008. const cmFrqTrkCh_t* c = p->ch + i;
  4009. if( !c->activeFl )
  4010. continue;
  4011. cmReal_t hz_min = c->hz * pow(2,-p->a.stRange/12.0);
  4012. cmReal_t hz_max = c->hz * pow(2, p->a.stRange/12.0);
  4013. unsigned j;
  4014. // find all peaks within the frequency range hz_min to hz_max.
  4015. for(j=0; j<pkN; ++j)
  4016. if( pkiV[j] != cmInvalidIdx && hz_min <= c->hz && c->hz <= hz_max )
  4017. pkiV[j] = cmInvalidIdx;
  4018. }
  4019. }
  4020. // Return the index into pkiV[] of the maximum energy peak in dbV[]
  4021. // that is also above kAtkThreshDb.
  4022. unsigned _cmFrqTrkMaxEnergyPeakIndex( const cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, const unsigned* pkiV, unsigned pkN )
  4023. {
  4024. cmReal_t mv = p->a.pkAtkThreshDb;
  4025. unsigned mi = cmInvalidIdx;
  4026. unsigned i;
  4027. for(i=0; i<pkN; ++i)
  4028. if( pkiV[i] != cmInvalidIdx && dbV[pkiV[i]] >= mv && hzV[pkiV[i]] < p->a.pkMaxHz )
  4029. {
  4030. mi = i;
  4031. mv = dbV[pkiV[i]];
  4032. }
  4033. return mi;
  4034. }
  4035. // start new trackers
  4036. void _cmFrqTrkNewChs( cmFrqTrk* p, const cmReal_t* dbV, const cmReal_t* hzV, unsigned* pkiV, unsigned pkN )
  4037. {
  4038. p->newTrkCnt = 0;
  4039. while(1)
  4040. {
  4041. unsigned db_max_idx;
  4042. cmFrqTrkCh_t* c;
  4043. // find an inactive channel
  4044. if((c = _cmFrqTrkFindAvailCh(p)) == NULL )
  4045. break;
  4046. // find the largest peak that is above pkAtkThreshDb && less than pkAtkHz.
  4047. if((db_max_idx = _cmFrqTrkMaxEnergyPeakIndex(p,dbV,hzV,pkiV,pkN)) == cmInvalidIdx )
  4048. break;
  4049. // activate a new channel
  4050. c->activeFl = true;
  4051. c->tN = 1;
  4052. c->dN = 0;
  4053. c->hz = hzV[ pkiV[ db_max_idx ] ];
  4054. c->db = dbV[ pkiV[ db_max_idx ] ];
  4055. c->id = p->nextTrkId++;
  4056. c->si = 0;
  4057. c->sn = 0;
  4058. c->score = 0;
  4059. c->state = kNoStateFrqTrkId;
  4060. c->attenPhsIdx = cmInvalidIdx;
  4061. c->attenGain = 1.0;
  4062. // mark the peak as unavailable
  4063. pkiV[ db_max_idx ] = cmInvalidIdx;
  4064. p->newTrkCnt += 1;
  4065. }
  4066. }
  4067. void _cmFrqTrkApplyFrqBias( cmFrqTrk* p, cmReal_t* xV )
  4068. {
  4069. // convert to decibel scale (0.0 - 100.0) and then scale to (0.0 to 1.0)
  4070. unsigned i;
  4071. for(i=0; i<p->bN; ++i)
  4072. xV[i] = cmMax(0.0, (20*log10( cmMax(xV[i]/1.5,0.00001)) + 100.0)/100.0);
  4073. }
  4074. cmRC_t cmFrqTrkExec( cmFrqTrk* p, const cmReal_t* magV, const cmReal_t* phsV, const cmReal_t* hertzV )
  4075. {
  4076. cmRC_t rc = cmOkRC;
  4077. cmReal_t hzV[ p->bN ];
  4078. //cmReal_t powV[ p->bN ];
  4079. //cmReal_t yV[ p->bN];
  4080. //cmVOR_MultVVV(powV,p->bN,magV,magV);
  4081. //cmWhFiltExec(p->wf,powV,p->dbV,p->bN);
  4082. // convert magV to Decibels
  4083. //cmVOR_AmplToDbVV(p->dbV,p->bN, magV, -200.0);
  4084. // copy p->dbV to dbM[hi,:]
  4085. //cmVOR_CopyN(p->dbM + p->hi, p->bN, p->hN, p->dbV, 1 );
  4086. //cmVOR_CopyN(p->dbM + p->hi, p->bN, p->hN, whV, 1 );
  4087. if( 1 )
  4088. {
  4089. cmReal_t powV[ p->bN ];
  4090. cmVOR_MultVVV(powV,p->bN,magV,magV);
  4091. cmWhFiltExec(p->wf,powV,p->dbV,p->bN);
  4092. _cmFrqTrkApplyFrqBias(p,p->dbV);
  4093. }
  4094. else
  4095. {
  4096. // convert magV to Decibels
  4097. cmVOR_AmplToDbVV(p->dbV,p->bN, magV, -200.0);
  4098. }
  4099. // copy p->dbV to dbM[hi,:]
  4100. cmVOR_CopyN(p->dbM + p->hi, p->bN, p->hN, p->dbV, 1 );
  4101. // increment hi to next column to fill in dbM[]
  4102. p->hi = (p->hi + 1) % p->hN;
  4103. // Set dbV[] to spectral magnitude profile by taking the mean over time
  4104. // of the last hN magnitude vectors
  4105. cmVOR_MeanM2(p->dbV, p->dbM, p->hN, p->bN, 0, cmMin(p->fN+1,p->hN));
  4106. //cmVOR_MeanM(p->dbV, p->dbM, p->hN, p->bN, 0);
  4107. if( p->fN >= p->hN )
  4108. {
  4109. // set pkiV[] to the indexes of the peaks above pkThreshDb in i0[]
  4110. unsigned pkN = cmVOR_PeakIndexes(p->pkiV, p->bN, p->dbV, p->bN, p->a.pkThreshDb );
  4111. // set hzV[] to the peak frequencies assoc'd with peaks at dbV[ pkiV[] ].
  4112. _cmFrqTrkMagnToHz(p, p->dbV, p->pkiV, pkN, hzV );
  4113. // extend the existing trackers
  4114. _cmFrqTrkExtendChs(p, p->dbV, hzV, p->pkiV, pkN );
  4115. //_cmFrqTrkDisableClosePeaks(p, p->dbV, hzV, p->pkiV, pkN );
  4116. // create new trackers
  4117. _cmFrqTrkNewChs(p,p->dbV,hzV,p->pkiV,pkN);
  4118. //
  4119. _cmFrqTrkScoreChs(p);
  4120. //
  4121. _cmFrqTrkUpdateFilter(p);
  4122. /*
  4123. // write the log file
  4124. _cmFrqTrkWriteLog(p);
  4125. // write the spectrum output file
  4126. if( p->specFn != NULL )
  4127. cmVectArrayAppendR(p->specVa,p->dbV,p->bN);
  4128. // write the atten output file
  4129. if( p->attenFn != NULL )
  4130. cmVectArrayAppendR(p->attenVa,p->aV,p->bN);
  4131. // write the the level file
  4132. _cmFrqTrkWriteLevel(p,p->dbV,hzV,p->bN);
  4133. */
  4134. }
  4135. p->fN += 1;
  4136. return rc;
  4137. }
  4138. void cmFrqTrkPrint( cmFrqTrk* p )
  4139. {
  4140. printf("srate: %f\n",p->a.srate);
  4141. printf("chCnt: %i\n",p->a.chCnt);
  4142. printf("binCnt: %i (bN=%i)\n",p->a.binCnt,p->bN);
  4143. printf("hopSmpCnt: %i\n",p->a.hopSmpCnt);
  4144. printf("stRange: %f\n",p->a.stRange);
  4145. printf("wndSecs: %f (%i)\n",p->a.wndSecs,p->hN);
  4146. printf("minTrkSec: %f (%i)\n",p->a.minTrkSec,p->minTrkN);
  4147. printf("maxTrkDeadSec: %f (%i)\n",p->a.maxTrkDeadSec,p->deadN_max);
  4148. printf("pkThreshDb: %f\n",p->a.pkThreshDb);
  4149. printf("pkAtkThreshDb: %f\n",p->a.pkAtkThreshDb);
  4150. }
  4151. //------------------------------------------------------------------------------------------------------------
  4152. cmFbCtl_t* cmFbCtlAlloc( cmCtx* c, cmFbCtl_t* ap, const cmFbCtlArgs_t* a )
  4153. {
  4154. cmFbCtl_t* p = cmObjAlloc( cmFbCtl_t, c, ap );
  4155. p->sva = cmVectArrayAlloc(c,kRealVaFl);
  4156. p->uva = cmVectArrayAlloc(c,kRealVaFl);
  4157. if( a != NULL )
  4158. {
  4159. if( cmFbCtlInit( p, a ) != cmOkRC )
  4160. cmFbCtlFree(&p);
  4161. }
  4162. return p;
  4163. }
  4164. cmRC_t cmFbCtlFree( cmFbCtl_t** pp )
  4165. {
  4166. if( pp == NULL || *pp == NULL )
  4167. return cmOkRC;
  4168. cmFbCtl_t* p = *pp;
  4169. cmVectArrayWrite(p->sva, "/home/kevin/temp/frqtrk/fb_ctl_s.va");
  4170. cmVectArrayWrite(p->uva, "/home/kevin/temp/frqtrk/fb_ctl_u.va");
  4171. cmMemFree(p->bM);
  4172. cmMemFree(p->rmsV);
  4173. cmVectArrayFree(&p->sva);
  4174. cmVectArrayFree(&p->uva);
  4175. cmObjFree(pp);
  4176. return cmOkRC;
  4177. }
  4178. cmRC_t cmFbCtlInit( cmFbCtl_t* p, const cmFbCtlArgs_t* a )
  4179. {
  4180. cmRC_t rc;
  4181. if((rc = cmFbCtlFinal(p)) != cmOkRC )
  4182. return rc;
  4183. double binHz = a->srate / ((a->binCnt-1)*2);
  4184. p->a = *a;
  4185. p->frmCnt = (a->bufMs * a->srate / 1000.0) /a->hopSmpCnt;
  4186. p->binCnt = cmMin(p->a.binCnt, a->maxHz/binHz);
  4187. p->bM = cmMemResizeZ(cmReal_t, p->bM, p->binCnt*p->frmCnt);
  4188. p->rmsV = cmMemResizeZ(cmReal_t, p->rmsV, p->frmCnt);
  4189. p->sV = cmMemResizeZ(cmReal_t, p->sV, p->binCnt);
  4190. p->uV = cmMemResizeZ(cmReal_t, p->uV, p->binCnt);
  4191. printf("cmFbCtl: frmCnt:%i binCnt:%i \n",p->frmCnt,p->binCnt);
  4192. return rc;
  4193. }
  4194. cmRC_t cmFbCtlFinal(cmFbCtl_t* p )
  4195. { return cmOkRC; }
  4196. cmRC_t cmFbCtlExec( cmFbCtl_t* p, const cmReal_t* x0V )
  4197. {
  4198. unsigned i;
  4199. cmRC_t rc = cmOkRC;
  4200. cmReal_t xV[ p->binCnt ];
  4201. cmVOR_AmplToDbVV(xV, p->binCnt, x0V, -1000.0 );
  4202. cmVOR_Shift( p->rmsV, p->frmCnt, -1, 0 );
  4203. p->rmsV[0] = cmVOR_Mean(xV,p->binCnt);
  4204. cmVOR_CopyN(p->bM + p->bfi, p->binCnt, p->frmCnt, xV, 1 );
  4205. p->bfi = (p->bfi + 1) % p->frmCnt;
  4206. p->bfN = cmMin(p->bfN+1,p->frmCnt);
  4207. for(i=0; i<p->binCnt; ++i)
  4208. {
  4209. const cmReal_t* v = p->bM + i * p->frmCnt;
  4210. cmReal_t u = cmVOR_Mean(v, p->bfN );
  4211. cmReal_t s = sqrt(cmVOR_Variance(v, p->bfN,&u));
  4212. p->sV[i] = (0.0002 - s);
  4213. p->uV[i] = u;
  4214. }
  4215. cmVectArrayAppendR(p->sva,p->sV,p->binCnt);
  4216. cmVectArrayAppendR(p->uva,p->uV,p->binCnt);
  4217. return rc;
  4218. }
  4219. //=======================================================================================================================
  4220. cmExpander* cmExpanderAlloc( cmCtx* c, cmExpander* p,
  4221. double srate, unsigned procSmpCnt, double threshDb, double rlsDb,
  4222. double threshMs, double rmsMs, double atkMs, double rlsMs )
  4223. {
  4224. cmExpander* op = cmObjAlloc(cmExpander,c,p);
  4225. if( srate > 0 )
  4226. if( cmExpanderInit(op,srate, procSmpCnt, threshDb, rlsDb, threshMs, rmsMs, atkMs, rlsMs) != cmOkRC )
  4227. cmExpanderFree(&op);
  4228. return op;
  4229. }
  4230. cmRC_t cmExpanderFree( cmExpander** pp )
  4231. {
  4232. cmRC_t rc = cmOkRC;
  4233. if( pp==NULL || *pp==NULL )
  4234. return rc;
  4235. cmExpander* p = *pp;
  4236. if((rc = cmExpanderFinal(p)) != cmOkRC )
  4237. return rc;
  4238. cmMemFree(p->rmsV);
  4239. cmMemFree(p->envV);
  4240. cmObjFree(pp);
  4241. return rc;
  4242. }
  4243. cmRC_t cmExpanderInit( cmExpander* p,
  4244. double srate, unsigned procSmpCnt, double threshDb, double rlsDb,
  4245. double threshMs, double rmsMs, double atkMs, double rlsMs )
  4246. {
  4247. cmRC_t rc;
  4248. unsigned i;
  4249. if((rc = cmExpanderFinal(p)) != cmOkRC )
  4250. return rc;
  4251. unsigned atkN = cmMax(1,ceil( atkMs / (srate * 1000.0)));
  4252. unsigned rlsN = cmMax(1,ceil( rlsMs / (srate * 1000.0)));
  4253. p->rmsN = cmMax(1,ceil(rmsMs / (srate * 1000.0)));
  4254. p->rmsV = cmMemResizeZ(cmReal_t,p->rmsV,p->rmsN);
  4255. p->rmsIdx = 0;
  4256. p->envN = atkN + rlsN;
  4257. p->envV = cmMemResizeZ(cmSample_t,p->envV,p->envN);
  4258. p->envIdx = p->envN;
  4259. p->threshN = cmMax(1,ceil(threshMs / (srate * 1000.0)));
  4260. p->threshIdx = 0;
  4261. p->threshLvl = pow(10.0,(threshDb/20.0));
  4262. p->rlsLvl = pow(10.0,(rlsDb/20.0));
  4263. p->gain = 1.0;
  4264. p->atkCnt = 0;
  4265. cmSample_t G = (1.0 - p->rlsLvl);
  4266. for(i=0; i<atkN; ++i)
  4267. {
  4268. p->envV[i] = 1.0 - G*i/atkN;
  4269. }
  4270. for(i=0; i<rlsN; ++i)
  4271. {
  4272. p->envV[atkN+i] = p->rlsLvl + (G*i/rlsN);
  4273. }
  4274. //printf("rmsN:%i atkN:%i rlsN:%i thr:%f %f rls:%f %f\n",p->rmsN,atkN,rlsN,threshDb,p->threshLvl,rlsDb,p->rlsLvl);
  4275. //for(i=0; i<p->envN; ++i)
  4276. // printf("%i %f\n",i,p->envV[i]);
  4277. //printf("\n");
  4278. return cmOkRC;
  4279. }
  4280. cmRC_t cmExpanderFinal( cmExpander* p )
  4281. { return cmOkRC; }
  4282. cmRC_t cmExpanderExec( cmExpander* p, cmSample_t* x, cmSample_t* y, unsigned xyN )
  4283. {
  4284. unsigned i;
  4285. // update the RMS buffer
  4286. for(i=0; i<xyN; ++i)
  4287. {
  4288. // NOTE: using abs() instead of pow(x,2)
  4289. p->rmsV[p->rmsIdx] = fabsf(x[i]);
  4290. if( ++p->rmsIdx >= p->rmsN )
  4291. p->rmsIdx = 0;
  4292. }
  4293. // calculate the RMS
  4294. double rms = cmVOR_Mean(p->rmsV,p->rmsN);
  4295. // update the duration that the signal has been above the threshold
  4296. if( rms > p->threshLvl )
  4297. p->threshIdx += 1;
  4298. else
  4299. p->threshIdx = 0;
  4300. // begin the atk phase?
  4301. if( p->threshIdx > p->threshN && p->envIdx >= p->envN )
  4302. {
  4303. p->envIdx = 0;
  4304. }
  4305. // update the output
  4306. if( p->envIdx >= p->envN )
  4307. {
  4308. if( y != NULL )
  4309. cmVOS_Copy(y,xyN,x);
  4310. }
  4311. else
  4312. {
  4313. if( y == NULL )
  4314. y = x;
  4315. for(i=0; i<xyN && p->envIdx<p->envN; ++i,++p->envIdx)
  4316. y[i] = p->envV[p->envIdx] * x[i];
  4317. }
  4318. return cmOkRC;
  4319. }
  4320. cmRC_t cmExpanderExecD( cmExpander* p, double* x, double* y, unsigned xyN )
  4321. {
  4322. unsigned i;
  4323. // update the RMS buffer
  4324. for(i=0; i<xyN; ++i)
  4325. {
  4326. // NOTE: using abs() instead of pow(x,2)
  4327. p->rmsV[p->rmsIdx] = x[i];
  4328. p->rmsIdx += 1;
  4329. if( p->rmsIdx >= p->rmsN )
  4330. p->rmsIdx = 0;
  4331. }
  4332. // calculate the RMS
  4333. p->rmsValue = cmVOR_Mean(p->rmsV,p->rmsN);
  4334. // update the duration that the signal has been above the threshold
  4335. if( p->rmsValue > p->threshLvl )
  4336. p->threshIdx += 1;
  4337. else
  4338. p->threshIdx = 0;
  4339. // begin the atk phase?
  4340. if( p->threshIdx > p->threshN && p->envIdx >= p->envN )
  4341. {
  4342. p->envIdx = 0;
  4343. p->atkCnt += 1;
  4344. }
  4345. /*
  4346. if( p->envIdx >= p->envN )
  4347. p->gain = 1.0;
  4348. else
  4349. {
  4350. p->gain = p->envV[p->envIdx];
  4351. p->envIdx += 1;
  4352. }
  4353. */
  4354. // update the output
  4355. if( p->envIdx >= p->envN )
  4356. {
  4357. if( y != NULL )
  4358. cmVOD_Copy(y,xyN,x);
  4359. }
  4360. else
  4361. {
  4362. if( y == NULL )
  4363. y = x;
  4364. for(i=0; i<xyN && p->envIdx<p->envN; ++i,++p->envIdx)
  4365. y[i] = p->envV[p->envIdx] * x[i];
  4366. }
  4367. return cmOkRC;
  4368. }
  4369. //=======================================================================================================================
  4370. cmExpanderBank* cmExpanderBankAlloc( cmCtx* c, cmExpanderBank* p, unsigned bandN, double srate, unsigned procSmpCnt, double threshDb, double rlsDb, double threshMs, double rmsMs, double atkMs, double rlsMs )
  4371. {
  4372. cmExpanderBank* op = cmObjAlloc(cmExpanderBank,c,p);
  4373. if( bandN > 0 )
  4374. if( cmExpanderBankInit(op,bandN,srate, procSmpCnt, threshDb, rlsDb, threshMs, rmsMs, atkMs, rlsMs) != cmOkRC )
  4375. cmExpanderBankFree(&op);
  4376. return op;
  4377. }
  4378. cmRC_t cmExpanderBankFree( cmExpanderBank** pp )
  4379. {
  4380. cmRC_t rc = cmOkRC;
  4381. if( pp==NULL || *pp==NULL )
  4382. return rc;
  4383. cmExpanderBank* p = *pp;
  4384. if((rc = cmExpanderBankFinal(p)) != cmOkRC )
  4385. return rc;
  4386. cmMemFree(p->b);
  4387. cmObjFree(pp);
  4388. return rc;
  4389. }
  4390. cmRC_t cmExpanderBankInit( cmExpanderBank* p, unsigned bandN, double srate, unsigned procSmpCnt, double threshDb, double rlsDb, double threshMs, double rmsMs, double atkMs, double rlsMs )
  4391. {
  4392. cmRC_t rc;
  4393. unsigned i;
  4394. if((rc = cmExpanderBankFinal(p)) != cmOkRC )
  4395. return rc;
  4396. p->bandN = bandN;
  4397. p->b = cmMemResizeZ(cmExpander*,p->b,p->bandN);
  4398. for(i=0; i<bandN; ++i)
  4399. p->b[i] = cmExpanderAlloc(p->obj.ctx,NULL,srate, procSmpCnt,threshDb,rlsDb,threshMs,rmsMs,atkMs,rlsMs);
  4400. return cmOkRC;
  4401. }
  4402. cmRC_t cmExpanderBankFinal( cmExpanderBank* p )
  4403. {
  4404. unsigned i;
  4405. for(i=0; i<p->bandN; ++i)
  4406. cmExpanderFree(&p->b[i]);
  4407. return cmOkRC;
  4408. }
  4409. cmRC_t cmExpanderBankExec( cmExpanderBank* p, cmSample_t* x, unsigned bandN )
  4410. {
  4411. assert( bandN <= p->bandN);
  4412. unsigned i;
  4413. for(i=0; i<bandN; ++i)
  4414. {
  4415. cmExpanderExec(p->b[i],&x[i],NULL,1);
  4416. }
  4417. return cmOkRC;
  4418. }
  4419. /*
  4420. cmRC_t cmExpanderBankExecD( cmExpanderBank* p, double* x, unsigned binN )
  4421. {
  4422. unsigned i;
  4423. p->rmsValue = 0;
  4424. for(i=0; i<p->bandN; ++i)
  4425. {
  4426. double sum = cmVOD_Sum(x,binN);
  4427. cmExpanderExecD(p->b[i],&sum,NULL,1);
  4428. //printf("%f %f\n",sum, p->b[i]->rmsValue);
  4429. p->rmsValue += p->b[i]->rmsValue;
  4430. cmVOR_MultVS(x,binN,p->b[i]->gain);
  4431. }
  4432. p->rmsValue /= p->bandN;
  4433. return cmOkRC;
  4434. }
  4435. */
  4436. cmRC_t cmExpanderBankExecD( cmExpanderBank* p, double* x, unsigned bandN )
  4437. {
  4438. unsigned i;
  4439. //unsigned n = 3;
  4440. //unsigned no2 = n/2;
  4441. double xx;
  4442. p->rmsValue = 0;
  4443. p->atkCnt = 0;
  4444. for(i=0; i<p->bandN; ++i)
  4445. {
  4446. unsigned atkCnt = p->b[i]->atkCnt;
  4447. //if( i >= no2 && i < bandN-no2 )
  4448. // xx = cmVOR_Mean(x-no2,n);
  4449. //else
  4450. xx = x[i];
  4451. cmExpanderExecD(p->b[i],&xx,NULL,1);
  4452. p->rmsValue += p->b[i]->rmsValue;
  4453. p->atkCnt += p->b[i]->atkCnt != atkCnt;
  4454. }
  4455. p->rmsValue /= p->bandN;
  4456. return cmOkRC;
  4457. }
  4458. //------------------------------------------------------------------------------------------------------------
  4459. cmSpecDist_t* cmSpecDistAlloc( cmCtx* ctx,cmSpecDist_t* ap, unsigned procSmpCnt, double srate, unsigned wndSmpCnt, unsigned hopFcmt, unsigned olaWndTypeId )
  4460. {
  4461. cmSpecDist_t* p = cmObjAlloc( cmSpecDist_t, ctx, ap );
  4462. //p->iSpecVa = cmVectArrayAlloc(ctx,kRealVaFl);
  4463. //p->oSpecVa = cmVectArrayAlloc(ctx,kRealVaFl);
  4464. p->statVa = cmVectArrayAlloc(ctx,kDoubleVaFl);
  4465. if( procSmpCnt != 0 )
  4466. {
  4467. if( cmSpecDistInit( p, procSmpCnt, srate, wndSmpCnt, hopFcmt, olaWndTypeId ) != cmOkRC )
  4468. cmSpecDistFree(&p);
  4469. }
  4470. return p;
  4471. }
  4472. cmRC_t cmSpecDistFree( cmSpecDist_t** pp )
  4473. {
  4474. if( pp == NULL || *pp == NULL )
  4475. return cmOkRC;
  4476. cmSpecDist_t* p = *pp;
  4477. cmSpecDistFinal(p);
  4478. //cmVectArrayFree(&p->iSpecVa);
  4479. //cmVectArrayFree(&p->oSpecVa);
  4480. cmVectArrayFree(&p->statVa);
  4481. cmMemPtrFree(&p->hzV);
  4482. cmMemPtrFree(&p->iSpecM);
  4483. cmMemPtrFree(&p->oSpecM);
  4484. cmMemPtrFree(&p->iSpecV);
  4485. cmMemPtrFree(&p->oSpecV);
  4486. cmObjFree(pp);
  4487. return cmOkRC;
  4488. }
  4489. cmRC_t cmSpecDistInit( cmSpecDist_t* p, unsigned procSmpCnt, double srate, unsigned wndSmpCnt, unsigned hopFcmt, unsigned olaWndTypeId )
  4490. {
  4491. //cmFrqTrkArgs_t fta;
  4492. cmRC_t rc;
  4493. if((rc = cmSpecDistFinal(p)) != cmOkRC )
  4494. return rc;
  4495. unsigned flags = 0;
  4496. p->srate = srate;
  4497. p->wndSmpCnt = wndSmpCnt;
  4498. p->hopSmpCnt = (unsigned)floor(wndSmpCnt/hopFcmt);
  4499. p->procSmpCnt = procSmpCnt;
  4500. p->mode = kBasicModeSdId;
  4501. p->thresh = 60;
  4502. p->offset = 0;
  4503. p->invertFl = false;
  4504. p->uprSlope = 0.0;
  4505. p->lwrSlope = 2.0;
  4506. p->pva = cmPvAnlAlloc( p->obj.ctx, NULL, procSmpCnt, srate, wndSmpCnt, p->hopSmpCnt, flags );
  4507. p->pvs = cmPvSynAlloc( p->obj.ctx, NULL, procSmpCnt, srate, wndSmpCnt, p->hopSmpCnt, olaWndTypeId );
  4508. /*
  4509. fta.srate = srate;
  4510. fta.chCnt = 50;
  4511. fta.binCnt = p->pva->binCnt;
  4512. fta.hopSmpCnt = p->pva->hopSmpCnt;
  4513. fta.stRange = 0.25;
  4514. fta.wndSecs = 0.25;
  4515. fta.minTrkSec = 0.25;
  4516. fta.maxTrkDeadSec = 0.25;
  4517. fta.pkThreshDb = 0.1; //-110.0;
  4518. fta.pkAtkThreshDb = 0.4; //-60.0;
  4519. fta.pkMaxHz = 20000;
  4520. fta.whFiltCoeff = 0.33;
  4521. fta.attenThresh = 0.4;
  4522. fta.attenGain = 0.5;
  4523. fta.attenDlySec = 1.0;
  4524. fta.attenAtkSec = 1.0;
  4525. fta.logFn = "/home/kevin/temp/frqtrk/trk_log.va";
  4526. fta.levelFn = "/home/kevin/temp/frqtrk/level.va";
  4527. fta.specFn = "/home/kevin/temp/frqtrk/spec.va";
  4528. fta.attenFn = "/home/kevin/temp/frqtrk/atten.va";
  4529. */
  4530. //p->ft = cmFrqTrkAlloc( p->obj.ctx, NULL, &fta );
  4531. /*
  4532. cmFbCtlArgs_t fba;
  4533. fba.srate = srate;
  4534. fba.binCnt = p->pva->binCnt;
  4535. fba.hopSmpCnt = p->hopSmpCnt;
  4536. fba.bufMs = 500;
  4537. fba.maxHz = 5000;
  4538. */
  4539. //p->fbc = cmFbCtlAlloc( p->obj.ctx, NULL, &fba );
  4540. //unsigned expBandN = 1; //
  4541. unsigned expBandN = 20000.0 / (p->srate / p->pva->binCnt);
  4542. double expSrate = p->pva->hopSmpCnt / srate;
  4543. unsigned expProcSmpCnt = 1;
  4544. double expThreshDb = -80.0;
  4545. double expRlsDb = -18.0;
  4546. double expThreshMs = 250.0;
  4547. double expRmsMs = 100.0;
  4548. double expAtkMs = 25.0;
  4549. double expRlsMs = 1000.0;
  4550. p->exb = cmExpanderBankAlloc( p->obj.ctx, NULL, expBandN, expSrate, expProcSmpCnt, expThreshDb, expRlsDb, expThreshMs, expRmsMs, expAtkMs, expRlsMs );
  4551. p->spcBwHz = cmMin(srate/2,10000);
  4552. p->spcSmArg = 0.05;
  4553. p->spcMin = p->spcBwHz;
  4554. p->spcMax = 0.0;
  4555. p->spcSum = 0.0;
  4556. p->spcCnt = 0;
  4557. double binHz = srate / p->pva->wndSmpCnt;
  4558. p->spcBinCnt = (unsigned)floor(p->spcBwHz / binHz);
  4559. p->hzV = cmMemResizeZ(cmReal_t,p->hzV,p->spcBinCnt);
  4560. cmVOR_Seq( p->hzV, p->spcBinCnt, 0, 1 );
  4561. cmVOR_MultVS( p->hzV, p->spcBinCnt, binHz );
  4562. p->aeUnit = 0;
  4563. p->aeMin = 1000;
  4564. p->aeMax = -1000;
  4565. double histSecs = 0.05;
  4566. p->hN = cmMax(1,histSecs * p->srate / p->hopSmpCnt );
  4567. p->iSpecM = cmMemResizeZ(cmReal_t,p->iSpecM,p->hN*p->pva->binCnt);
  4568. p->oSpecM = cmMemResizeZ(cmReal_t,p->oSpecM,p->hN*p->pva->binCnt);
  4569. p->iSpecV = cmMemResizeZ(cmReal_t,p->iSpecV, p->pva->binCnt);
  4570. p->oSpecV = cmMemResizeZ(cmReal_t,p->oSpecV, p->pva->binCnt);
  4571. p->hi = 0;
  4572. //p->bypOut = cmMemResizeZ(cmSample_t, p->bypOut, procSmpCnt );
  4573. return rc;
  4574. }
  4575. cmRC_t cmSpecDistFinal(cmSpecDist_t* p )
  4576. {
  4577. cmRC_t rc = cmOkRC;
  4578. //cmVectArrayWrite(p->iSpecVa, "/home/kevin/temp/frqtrk/iSpec.va");
  4579. //cmVectArrayWrite(p->oSpecVa, "/home/kevin/temp/expand/oSpec.va");
  4580. //cmVectArrayWrite(p->statVa, "/Users/kevin/temp/kc/state.va");
  4581. cmPvAnlFree(&p->pva);
  4582. cmPvSynFree(&p->pvs);
  4583. //cmFrqTrkFree(&p->ft);
  4584. //cmFbCtlFree(&p->fbc);
  4585. cmExpanderBankFree(&p->exb);
  4586. return rc;
  4587. }
  4588. void _cmSpecDistBasicMode0(cmSpecDist_t* p, cmReal_t* X1m, unsigned binCnt, cmReal_t thresh )
  4589. {
  4590. // octavez> thresh = 60;
  4591. // octave> X1m = [-62 -61 -60 -59];
  4592. // octave> -abs(abs(X1m+thresh)-(X1m+thresh)) - thresh
  4593. // octave> ans = -64 -62 -60 -60
  4594. /*
  4595. unsigned i=0;
  4596. for(i=0; i<binCnt; ++i)
  4597. {
  4598. cmReal_t a = fabs(X1m[i]);
  4599. cmReal_t d = a - thresh;
  4600. X1m[i] = -thresh;
  4601. if( d > 0 )
  4602. X1m[i] -= 2*d;
  4603. }
  4604. */
  4605. unsigned i=0;
  4606. for(i=0; i>binCnt; ++i)
  4607. {
  4608. X1m[i] = -fabs(fabs(X1m[i]-thresh) - (X1m[i]-thresh)) - thresh;
  4609. }
  4610. }
  4611. void _cmSpecDistBasicMode(cmSpecDist_t* p, cmReal_t* X1m, unsigned binCnt, cmReal_t thresh )
  4612. {
  4613. unsigned i=0;
  4614. if( p->lwrSlope < 0.3 )
  4615. p->lwrSlope = 0.3;
  4616. for(i=0; i<binCnt; ++i)
  4617. {
  4618. cmReal_t a = fabs(X1m[i]);
  4619. cmReal_t d = a - thresh;
  4620. X1m[i] = -thresh;
  4621. if( d > 0 )
  4622. X1m[i] -= (p->lwrSlope*d);
  4623. else
  4624. X1m[i] -= (p->uprSlope*d);
  4625. }
  4626. }
  4627. cmReal_t _cmSpecDistCentMode( cmSpecDist_t* p, cmReal_t* X1m )
  4628. {
  4629. // calc the spectral centroid
  4630. double num = cmVOR_MultSumVV( p->pva->magV, p->hzV, p->spcBinCnt );
  4631. double den = cmVOR_Sum( p->pva->magV, p->spcBinCnt );
  4632. double result = 0;
  4633. if( den != 0 )
  4634. result = num/den;
  4635. // apply smoothing filter to spectral centroid
  4636. p->spc = (result * p->spcSmArg) + (p->spc * (1.0-p->spcSmArg));
  4637. // track spec. cetr. min and max
  4638. p->spcMin = cmMin(p->spcMin,p->spc);
  4639. p->spcMax = cmMax(p->spcMax,p->spc);
  4640. //-----------------------------------------------------
  4641. ++p->spcCnt;
  4642. p->spcSum += p->spc;
  4643. p->spcSqSum += p->spc * p->spc;
  4644. // use the one-pass std-dev calc. trick
  4645. //double mean = p->spcSum / p->spcCnt;
  4646. //double variance = p->spcSqSum / p->spcCnt - mean * mean;
  4647. //double std_dev = sqrt(variance);
  4648. double smin = p->spcMin;
  4649. double smax = p->spcMax;
  4650. //smin = mean - std_dev;
  4651. //smax = mean + std_dev;
  4652. //-----------------------------------------------------
  4653. // convert spec. cent. to unit range
  4654. double spcUnit = (p->spc - smin) / (smax - smin);
  4655. spcUnit = cmMin(1.0,cmMax(0.0,spcUnit));
  4656. if( p->invertFl )
  4657. spcUnit = 1.0 - spcUnit;
  4658. //if( p->spcMin==p->spc || p->spcMax==p->spc )
  4659. // printf("min:%f avg:%f sd:%f max:%f\n",p->spcMin,p->spcSum/p->spcCnt,std_dev,p->spcMax);
  4660. return spcUnit;
  4661. }
  4662. void _cmSpecDistBump( cmSpecDist_t* p, cmReal_t* x, unsigned binCnt, double thresh)
  4663. {
  4664. /*
  4665. thresh *= -1;
  4666. minDb = -100;
  4667. if db < minDb
  4668. db = minDb;
  4669. endif
  4670. if db > thresh
  4671. y = 1;
  4672. else
  4673. x = (minDb - db)/(minDb - thresh);
  4674. y = x + (x - (x.^coeff));
  4675. endif
  4676. y = minDb + abs(minDb) * y;
  4677. */
  4678. unsigned i=0;
  4679. //printf("%f %f %f\n",thresh,p->lwrSlope,x[0]);
  4680. double minDb = -100.0;
  4681. thresh = -thresh;
  4682. for(i=0; i<binCnt; ++i)
  4683. {
  4684. double y;
  4685. if( x[i] < minDb )
  4686. x[i] = minDb;
  4687. if( x[i] > thresh )
  4688. y = 1;
  4689. else
  4690. {
  4691. y = (minDb - x[i])/(minDb - thresh);
  4692. y += y - pow(y,p->lwrSlope);
  4693. }
  4694. x[i] = minDb + (-minDb) * y;
  4695. }
  4696. }
  4697. void _cmSpecDistAmpEnvMode( cmSpecDist_t* p, cmReal_t* X1m )
  4698. {
  4699. cmReal_t smCoeff = 0.1;
  4700. //
  4701. cmReal_t mx = cmVOR_Max(X1m,p->pva->binCnt,1);
  4702. p->aeSmMax = (mx * smCoeff) + (p->aeSmMax * (1.0-smCoeff));
  4703. cmReal_t a = cmVOR_Mean(X1m,p->pva->binCnt);
  4704. p->ae = (a * smCoeff) + (p->ae * (1.0-smCoeff));
  4705. p->aeMin = cmMin(p->ae,p->aeMin);
  4706. p->aeMax = cmMax(p->ae,p->aeMax);
  4707. p->aeUnit = (p->ae - p->aeMin) / (p->aeMax-p->aeMin);
  4708. p->aeUnit = cmMin(1.0,cmMax(0.0,p->aeUnit));
  4709. if( p->invertFl )
  4710. p->aeUnit = 1.0 - p->aeUnit;
  4711. //printf("%f\n",p->aeSmMax);
  4712. }
  4713. void _cmSpecDistPhaseMod( cmSpecDist_t* p, cmReal_t* phsV, unsigned binCnt )
  4714. {
  4715. unsigned i;
  4716. cmReal_t offs = sin( 0.1 * 2.0 * M_PI * (p->phaseModIndex++) / (p->srate/p->hopSmpCnt) );
  4717. //printf("offs %f %i %i %f\n",offs,p->phaseModIndex,p->hopSmpCnt,p->srate);
  4718. cmReal_t new_phs = phsV[0] + offs;
  4719. for(i=0; i<binCnt-1; ++i)
  4720. {
  4721. while( new_phs > M_PI )
  4722. new_phs -= 2.0*M_PI;
  4723. while( new_phs < -M_PI )
  4724. new_phs += 2.0*M_PI;
  4725. cmReal_t d = phsV[i+1] - phsV[i];
  4726. phsV[i] = new_phs;
  4727. new_phs += d;
  4728. }
  4729. }
  4730. cmRC_t cmSpecDistExec( cmSpecDist_t* p, const cmSample_t* sp, unsigned sn )
  4731. {
  4732. assert( sn == p->procSmpCnt );
  4733. bool recordFl = false;
  4734. // cmPvAnlExec() returns true when it calc's a new spectral output frame
  4735. if( cmPvAnlExec( p->pva, sp, sn ) )
  4736. {
  4737. cmReal_t X1m[p->pva->binCnt];
  4738. // take the mean of the the input magntitude spectrum
  4739. cmReal_t u0 = cmVOR_Mean(p->pva->magV,p->pva->binCnt);
  4740. if(recordFl)
  4741. {
  4742. // store a time windowed average of the input spectrum to p->iSpecV
  4743. cmVOR_CopyN(p->iSpecM + p->hi, p->pva->binCnt, p->hN, X1m, 1 );
  4744. cmVOR_MeanM2(p->iSpecV, p->iSpecM, p->hN, p->pva->binCnt, 0, cmMin(p->fi+1,p->hN));
  4745. }
  4746. cmVOR_PowVS(X1m,p->pva->binCnt,2.0);
  4747. cmVOR_AmplToDbVV(X1m, p->pva->binCnt, p->pva->magV, -1000.0 );
  4748. //cmVOR_AmplToDbVV(X1m, p->pva->binCnt, X1m, -1000.0 );
  4749. switch( p->mode )
  4750. {
  4751. case kBypassModeSdId:
  4752. break;
  4753. case kBasicModeSdId:
  4754. _cmSpecDistBasicMode(p,X1m,p->pva->binCnt,p->thresh);
  4755. break;
  4756. case kSpecCentSdId:
  4757. {
  4758. _cmSpecDistAmpEnvMode(p,X1m);
  4759. double spcUnit = _cmSpecDistCentMode(p,X1m);
  4760. double thresh = fabs(p->aeSmMax) - (spcUnit*p->offset);
  4761. _cmSpecDistBasicMode(p,X1m,p->pva->binCnt, thresh);
  4762. }
  4763. break;
  4764. case kAmpEnvSdId:
  4765. {
  4766. _cmSpecDistAmpEnvMode(p,X1m);
  4767. //double thresh = fabs(p->aeSmMax) - p->offset;
  4768. double thresh = fabs(p->aeSmMax) - (p->aeUnit*p->offset);
  4769. thresh = fabs(p->thresh) - (p->aeUnit*p->offset);
  4770. _cmSpecDistBasicMode(p,X1m,p->pva->binCnt, thresh);
  4771. }
  4772. break;
  4773. case kBumpSdId:
  4774. _cmSpecDistBump(p,X1m, p->pva->binCnt, p->offset);
  4775. _cmSpecDistBasicMode(p,X1m,p->pva->binCnt,p->thresh);
  4776. break;
  4777. case 5:
  4778. break;
  4779. default:
  4780. break;
  4781. }
  4782. cmVOR_DbToAmplVV(X1m, p->pva->binCnt, X1m );
  4783. // run and apply the tracker/supressor
  4784. //cmFrqTrkExec(p->ft, X1m, p->pva->phsV, NULL );
  4785. //cmVOR_MultVV(X1m, p->pva->binCnt,p->ft->aV );
  4786. // convert the mean input magnitude to db
  4787. cmReal_t idb = 20*log10(u0);
  4788. // get the mean output magnitude spectra
  4789. cmReal_t u1 = cmVOR_Mean(X1m,p->pva->binCnt);
  4790. if( idb > -150.0 )
  4791. {
  4792. // set the output gain such that the mean output magnitude
  4793. // will match the mean input magnitude
  4794. p->ogain = u0/u1;
  4795. }
  4796. else
  4797. {
  4798. cmReal_t a0 = 0.9;
  4799. p->ogain *= a0;
  4800. }
  4801. double g = u0/u1;
  4802. p->ogain0 = g + (p->ogain0 * .98);
  4803. //double v[] = { u0, u1, p->ogain, p->ogain0 };
  4804. //cmVectArrayAppendD(p->statVa,v,sizeof(v)/sizeof(v[0]));
  4805. cmVOR_MultVS(X1m,p->pva->binCnt,cmMin(4.0,p->ogain));
  4806. //cmFbCtlExec(p->fbc,X1m);
  4807. //cmReal_t v[ p->pva->binCnt ];
  4808. //cmVOR_Copy(v,p->pva->binCnt,p->pva->phsV);
  4809. //_cmSpecDistPhaseMod(p, v, p->pva->binCnt );
  4810. if(recordFl)
  4811. {
  4812. // store a time windowed average of the output spectrum to p->iSpecV
  4813. cmVOR_CopyN(p->oSpecM + p->hi, p->pva->binCnt, p->hN, X1m, 1 );
  4814. cmVOR_MeanM2(p->oSpecV, p->oSpecM, p->hN, p->pva->binCnt, 0, cmMin(p->fi+1,p->hN));
  4815. // store iSpecV and oSpecV to iSpecVa and oSpecVa to create debugging files
  4816. //cmVectArrayAppendR(p->iSpecVa,p->iSpecV,p->pva->binCnt);
  4817. //cmVectArrayAppendR(p->oSpecVa,p->oSpecV,p->pva->binCnt);
  4818. p->hi = (p->hi + 1) % p->hN;
  4819. }
  4820. //unsigned binN = 12500.0 / (p->srate / p->pva->binCnt);
  4821. //cmExpanderBankExecD(p->exb, X1m, binN );
  4822. /*
  4823. cmExpanderBankExecD(p->exb, X1m, p->exb->bandN );
  4824. cmReal_t mean = cmVOR_Mean(X1m,p->exb->bandN);
  4825. cmReal_t arr[3] = { p->exb->rmsValue, mean, p->exb->atkCnt };
  4826. cmVectArrayAppendR(p->oSpecVa,arr,3);
  4827. */
  4828. cmPvSynExec(p->pvs, X1m, p->pva->phsV );
  4829. p->fi += 1;
  4830. }
  4831. return cmOkRC;
  4832. }
  4833. const cmSample_t* cmSpecDistOut( cmSpecDist_t* p )
  4834. {
  4835. return cmPvSynExecOut(p->pvs);
  4836. }
  4837. //------------------------------------------------------------------------------------------------------------
  4838. cmSpecDist2_t* cmSpecDist2Alloc( cmCtx* ctx,cmSpecDist2_t* ap, unsigned procSmpCnt, double srate, unsigned wndSmpCnt, unsigned hopFcmt, unsigned olaWndTypeId )
  4839. {
  4840. cmSpecDist2_t* p = cmObjAlloc( cmSpecDist2_t, ctx, ap );
  4841. if( procSmpCnt != 0 )
  4842. {
  4843. if( cmSpecDist2Init( p, procSmpCnt, srate, wndSmpCnt, hopFcmt, olaWndTypeId ) != cmOkRC )
  4844. cmSpecDist2Free(&p);
  4845. }
  4846. return p;
  4847. }
  4848. cmRC_t cmSpecDist2Free( cmSpecDist2_t** pp )
  4849. {
  4850. if( pp == NULL || *pp == NULL )
  4851. return cmOkRC;
  4852. cmSpecDist2_t* p = *pp;
  4853. cmSpecDist2Final(p);
  4854. cmObjFree(pp);
  4855. return cmOkRC;
  4856. }
  4857. cmRC_t cmSpecDist2Init( cmSpecDist2_t* p, unsigned procSmpCnt, double srate, unsigned wndSmpCnt, unsigned hopFcmt, unsigned olaWndTypeId )
  4858. {
  4859. cmRC_t rc;
  4860. if((rc = cmSpecDist2Final(p)) != cmOkRC )
  4861. return rc;
  4862. unsigned flags = 0;
  4863. p->srate = srate;
  4864. p->wndSmpCnt = wndSmpCnt;
  4865. p->hopSmpCnt = (unsigned)floor(wndSmpCnt/hopFcmt);
  4866. p->procSmpCnt = procSmpCnt;
  4867. p->igain = 1.0;
  4868. p->ceiling = 30;
  4869. p->expo = 2.0;
  4870. p->thresh = 60;
  4871. p->uprSlope = 0.0;
  4872. p->lwrSlope = 2.0;
  4873. p->mix = 0.0;
  4874. p->igainV = cmMemResizeZ( cmSample_t, p->igainV, procSmpCnt );
  4875. p->pva = cmPvAnlAlloc( p->obj.ctx, NULL, procSmpCnt, srate, wndSmpCnt, p->hopSmpCnt, flags );
  4876. p->pvs = cmPvSynAlloc( p->obj.ctx, NULL, procSmpCnt, srate, wndSmpCnt, p->hopSmpCnt, olaWndTypeId );
  4877. return rc;
  4878. }
  4879. cmRC_t cmSpecDist2Final(cmSpecDist2_t* p )
  4880. {
  4881. cmRC_t rc = cmOkRC;
  4882. cmMemFree(p->igainV);
  4883. cmPvAnlFree(&p->pva);
  4884. cmPvSynFree(&p->pvs);
  4885. return rc;
  4886. }
  4887. void _cmSpecDist2Bump( cmSpecDist2_t* p, cmReal_t* x, unsigned binCnt, double thresh, double expo)
  4888. {
  4889. unsigned i = 0;
  4890. double minDb = -100.0;
  4891. thresh = -fabs(thresh);
  4892. for(i=0; i<binCnt; ++i)
  4893. {
  4894. double y;
  4895. if( x[i] < minDb )
  4896. x[i] = minDb;
  4897. if( x[i] > thresh )
  4898. y = 1;
  4899. else
  4900. {
  4901. y = (minDb - x[i])/(minDb - thresh);
  4902. y += y - pow(y,expo);
  4903. }
  4904. x[i] = minDb + (-minDb) * y;
  4905. }
  4906. }
  4907. void _cmSpecDist2BasicMode(cmSpecDist2_t* p, cmReal_t* X1m, unsigned binCnt, cmReal_t thresh, double upr, double lwr )
  4908. {
  4909. unsigned i=0;
  4910. if( lwr < 0.3 )
  4911. lwr = 0.3;
  4912. for(i=0; i<binCnt; ++i)
  4913. {
  4914. cmReal_t a = fabs(X1m[i]);
  4915. cmReal_t d = a - thresh;
  4916. X1m[i] = -thresh;
  4917. if( d > 0 )
  4918. X1m[i] -= (lwr*d);
  4919. else
  4920. X1m[i] -= (upr*d);
  4921. }
  4922. }
  4923. cmRC_t cmSpecDist2Exec( cmSpecDist2_t* p, const cmSample_t* sp, unsigned sn )
  4924. {
  4925. assert( sn == p->procSmpCnt );
  4926. unsigned binN = p->pva->binCnt;
  4927. cmVOS_MultVVS( p->igainV, sn, sp, p->igain );
  4928. //printf("%f\n",p->igainV[0]);
  4929. // cmPvAnlExec() returns true when it calc's a new spectral output frame
  4930. if( cmPvAnlExec( p->pva, p->igainV, sn ) )
  4931. {
  4932. cmReal_t X0m[binN];
  4933. cmReal_t X1m[binN];
  4934. // take the mean of the the input magntitude spectrum
  4935. cmReal_t u0 = cmVOR_Mean(p->pva->magV,binN);
  4936. // convert magnitude to db (range=-1000.0 to 0.0)
  4937. cmVOR_AmplToDbVV(X0m, binN, p->pva->magV, -1000.0 );
  4938. cmVOR_Copy(X1m,binN,X0m);
  4939. // bump transform X0m
  4940. _cmSpecDist2Bump(p,X0m, binN, p->ceiling, p->expo);
  4941. // xfade bump output with raw input: X1m = (X0m*mix) + (X1m*(1.0-mix))
  4942. cmVOR_MultVS(X0m,binN,p->mix);
  4943. cmVOR_MultVS(X1m,binN,1.0 - p->mix );
  4944. cmVOR_AddVV(X1m,binN,X0m);
  4945. // basic transform
  4946. _cmSpecDist2BasicMode(p,X1m,binN,p->thresh,p->uprSlope,p->lwrSlope);
  4947. // convert db back to magnitude
  4948. cmVOR_DbToAmplVV(X1m, binN, X1m );
  4949. // convert the mean input magnitude to db
  4950. cmReal_t idb = 20*log10(u0);
  4951. // get the mean output magnitude spectra
  4952. cmReal_t u1 = cmVOR_Mean(X1m,binN);
  4953. if( idb > -150.0 )
  4954. {
  4955. // set the output gain such that the mean output magnitude
  4956. // will match the mean input magnitude
  4957. p->ogain = u0/u1;
  4958. }
  4959. else
  4960. {
  4961. cmReal_t a0 = 0.9;
  4962. p->ogain *= a0;
  4963. }
  4964. // apply the output gain
  4965. cmVOR_MultVS(X1m,binN,cmMin(4.0,p->ogain));
  4966. // convert back to time domain
  4967. cmPvSynExec(p->pvs, X1m, p->pva->phsV );
  4968. p->fi += 1;
  4969. }
  4970. return cmOkRC;
  4971. }
  4972. const cmSample_t* cmSpecDist2Out( cmSpecDist2_t* p )
  4973. {
  4974. return cmPvSynExecOut(p->pvs);
  4975. }
  4976. void cmSpecDist2Report( cmSpecDist2_t* p )
  4977. {
  4978. printf("igain:%f ceil:%f expo:%f mix:%f thresh:%f upr:%f lwr:%f\n", p->igain, p->ceiling,p->expo,p->mix,p->thresh,p->lwrSlope,p->uprSlope);
  4979. }
  4980. //------------------------------------------------------------------------------------------------------------
  4981. cmRC_t _cmBinMtxFileWriteHdr( cmBinMtxFile_t* p )
  4982. {
  4983. cmFileRC_t fileRC;
  4984. unsigned n = 3;
  4985. unsigned hdr[n];
  4986. hdr[0] = p->rowCnt;
  4987. hdr[1] = p->maxRowEleCnt;
  4988. hdr[2] = p->eleByteCnt;
  4989. if((fileRC = cmFileSeek(p->fh,kBeginFileFl,0)) != kOkFileRC )
  4990. return cmCtxRtCondition(&p->obj, fileRC, "File seek failed on matrix file:'%s'.", cmStringNullGuard(cmFileName(p->fh)));
  4991. if((fileRC = cmFileWriteUInt(p->fh,hdr,n)) != kOkFileRC )
  4992. return cmCtxRtCondition( &p->obj, fileRC, "Header write failed on matrix file:'%s'.", cmStringNullGuard(cmFileName(p->fh)) );
  4993. return cmOkRC;
  4994. }
  4995. cmBinMtxFile_t* cmBinMtxFileAlloc( cmCtx* ctx, cmBinMtxFile_t* ap, const cmChar_t* fn )
  4996. {
  4997. cmBinMtxFile_t* p = cmObjAlloc( cmBinMtxFile_t, ctx, ap );
  4998. if( fn != NULL )
  4999. if( cmBinMtxFileInit( p, fn ) != cmOkRC )
  5000. cmBinMtxFileFree(&p);
  5001. return p;
  5002. }
  5003. cmRC_t cmBinMtxFileFree( cmBinMtxFile_t** pp )
  5004. {
  5005. cmRC_t rc;
  5006. if( pp==NULL || *pp == NULL )
  5007. return cmOkRC;
  5008. cmBinMtxFile_t* p = *pp;
  5009. if((rc = cmBinMtxFileFinal(p)) == cmOkRC )
  5010. {
  5011. cmObjFree(pp);
  5012. }
  5013. return rc;
  5014. }
  5015. cmRC_t cmBinMtxFileInit( cmBinMtxFile_t* p, const cmChar_t* fn )
  5016. {
  5017. cmRC_t rc;
  5018. cmFileRC_t fileRC;
  5019. if((rc = cmBinMtxFileFinal(p)) != cmOkRC )
  5020. return rc;
  5021. // open the output file for writing
  5022. if((fileRC = cmFileOpen(&p->fh,fn,kWriteFileFl | kBinaryFileFl, p->obj.err.rpt)) != kOkFileRC )
  5023. return cmCtxRtCondition( &p->obj, fileRC, "Unable to open the matrix file:'%s'", cmStringNullGuard(fn) );
  5024. // iniitlaize the object
  5025. p->rowCnt = 0;
  5026. p->maxRowEleCnt = 0;
  5027. p->eleByteCnt = 0;
  5028. // write the blank header as place holder
  5029. if((rc = _cmBinMtxFileWriteHdr(p)) != cmOkRC )
  5030. return rc;
  5031. return rc;
  5032. }
  5033. cmRC_t cmBinMtxFileFinal( cmBinMtxFile_t* p )
  5034. {
  5035. cmRC_t rc;
  5036. cmFileRC_t fileRC;
  5037. if( p != NULL && cmFileIsValid(p->fh))
  5038. {
  5039. // re-write the file header
  5040. if((rc = _cmBinMtxFileWriteHdr(p)) != cmOkRC )
  5041. return rc;
  5042. // close the file
  5043. if((fileRC = cmFileClose(&p->fh)) != kOkFileRC )
  5044. return cmCtxRtCondition(&p->obj, fileRC, "Matrix file close failed on:'%s'",cmStringNullGuard(cmFileName(p->fh)));
  5045. }
  5046. return cmOkRC;
  5047. }
  5048. bool cmBinMtxFileIsValid( cmBinMtxFile_t* p )
  5049. { return p != NULL && cmFileIsValid(p->fh); }
  5050. cmRC_t _cmBinMtxFileWriteRow( cmBinMtxFile_t* p, const void* buf, unsigned eleCnt, unsigned eleByteCnt )
  5051. {
  5052. cmFileRC_t fileRC;
  5053. if((fileRC = cmFileWrite(p->fh,&eleCnt,sizeof(eleCnt))) != kOkFileRC )
  5054. return cmCtxRtCondition(&p->obj, fileRC, "Matrix file row at index %i element count write failed on '%s'.", p->rowCnt, cmStringNullGuard(cmFileName(p->fh)));
  5055. if((fileRC = cmFileWrite(p->fh,buf,eleCnt*eleByteCnt)) != kOkFileRC )
  5056. return cmCtxRtCondition(&p->obj, fileRC, "Matrix file row at index %i data write failed on '%s'.", p->rowCnt, cmStringNullGuard(cmFileName(p->fh)));
  5057. if( eleCnt > p->maxRowEleCnt )
  5058. p->maxRowEleCnt = eleCnt;
  5059. ++p->rowCnt;
  5060. return cmOkRC;
  5061. }
  5062. cmRC_t cmBinMtxFileExecS( cmBinMtxFile_t* p, const cmSample_t* x, unsigned xn )
  5063. {
  5064. // verify that all rows are written as cmSample_t
  5065. assert( p->eleByteCnt == 0 || p->eleByteCnt == sizeof(cmSample_t));
  5066. p->eleByteCnt = sizeof(cmSample_t);
  5067. return _cmBinMtxFileWriteRow(p,x,xn,p->eleByteCnt);
  5068. }
  5069. cmRC_t cmBinMtxFileExecR( cmBinMtxFile_t* p, const cmReal_t* x, unsigned xn )
  5070. {
  5071. // verify that all rows are written as cmReal_t
  5072. assert( p->eleByteCnt == 0 || p->eleByteCnt == sizeof(cmReal_t));
  5073. p->eleByteCnt = sizeof(cmReal_t);
  5074. return _cmBinMtxFileWriteRow(p,x,xn,p->eleByteCnt);
  5075. }
  5076. cmRC_t cmBinMtxFileWrite( const cmChar_t* fn, unsigned rowCnt, unsigned colCnt, const cmSample_t* sp, const cmReal_t* rp, cmCtx* ctx, cmRpt_t* rpt )
  5077. {
  5078. assert( sp == NULL || rp == NULL );
  5079. cmCtx* ctxp = NULL;
  5080. cmBinMtxFile_t* bp = NULL;
  5081. if( ctx == NULL )
  5082. ctx = ctxp = cmCtxAlloc(NULL,rpt,cmLHeapNullHandle,cmSymTblNullHandle);
  5083. if((bp = cmBinMtxFileAlloc(ctx,NULL,fn)) != NULL )
  5084. {
  5085. unsigned i = 0;
  5086. cmSample_t* sbp = sp == NULL ? NULL : cmMemAlloc(cmSample_t,colCnt);
  5087. cmReal_t* rbp = rp == NULL ? NULL : cmMemAlloc(cmReal_t,colCnt);
  5088. for(i=0; i<rowCnt; ++i)
  5089. {
  5090. if( sp!=NULL )
  5091. {
  5092. cmVOS_CopyN(sbp,colCnt,1,sp+i,rowCnt);
  5093. cmBinMtxFileExecS(bp,sbp,colCnt);
  5094. }
  5095. if( rp!=NULL )
  5096. {
  5097. cmVOR_CopyN(rbp,colCnt,1,rp+i,rowCnt);
  5098. cmBinMtxFileExecR(bp,rbp,colCnt);
  5099. }
  5100. }
  5101. cmMemPtrFree(&sbp);
  5102. cmMemPtrFree(&rbp);
  5103. cmBinMtxFileFree(&bp);
  5104. }
  5105. if( ctxp != NULL )
  5106. cmCtxFree(&ctxp);
  5107. return cmOkRC;
  5108. }
  5109. cmRC_t _cmBinMtxFileReadHdr( cmCtx_t* ctx, cmFileH_t h, unsigned* rowCntPtr, unsigned* colCntPtr, unsigned* eleByteCntPtr, const cmChar_t* fn )
  5110. {
  5111. cmRC_t rc = cmOkRC;
  5112. unsigned hdr[3];
  5113. if( cmFileRead(h,&hdr,sizeof(hdr)) != kOkFileRC )
  5114. {
  5115. rc = cmErrMsg(&ctx->err,cmSubSysFailRC,"Binary matrix file header read failed on '%s'.",cmStringNullGuard(fn));
  5116. goto errLabel;
  5117. }
  5118. if( rowCntPtr != NULL )
  5119. *rowCntPtr = hdr[0];
  5120. if( colCntPtr != NULL )
  5121. *colCntPtr = hdr[1];
  5122. if( eleByteCntPtr != NULL )
  5123. *eleByteCntPtr = hdr[2];
  5124. errLabel:
  5125. return rc;
  5126. }
  5127. cmRC_t cmBinMtxFileSize( cmCtx_t* ctx, const cmChar_t* fn, unsigned* rowCntPtr, unsigned* colCntPtr, unsigned* eleByteCntPtr )
  5128. {
  5129. cmFileH_t h = cmFileNullHandle;
  5130. cmRC_t rc = cmOkRC;
  5131. if(cmFileOpen(&h,fn,kReadFileFl | kBinaryFileFl, ctx->err.rpt) != kOkFileRC )
  5132. {
  5133. rc = cmErrMsg(&ctx->err,cmSubSysFailRC,"Binary matrix file:%s open failed.",cmStringNullGuard(fn));
  5134. goto errLabel;
  5135. }
  5136. rc = _cmBinMtxFileReadHdr(ctx,h,rowCntPtr,colCntPtr,eleByteCntPtr,fn);
  5137. errLabel:
  5138. cmFileClose(&h);
  5139. return rc;
  5140. }
  5141. cmRC_t cmBinMtxFileRead( cmCtx_t* ctx, const cmChar_t* fn, unsigned mRowCnt, unsigned mColCnt, unsigned mEleByteCnt, void* retBuf, unsigned* colCntV )
  5142. {
  5143. cmFileH_t h = cmFileNullHandle;
  5144. cmRC_t rc = cmOkRC;
  5145. char* rowBuf = NULL;
  5146. unsigned rowCnt,colCnt,eleByteCnt,i;
  5147. cmErr_t err;
  5148. cmErrSetup(&err,ctx->err.rpt,"Binary Matrix File Reader");
  5149. if(cmFileOpen(&h,fn,kReadFileFl | kBinaryFileFl, err.rpt) != kOkFileRC )
  5150. {
  5151. rc = cmErrMsg(&err,cmSubSysFailRC,"Binary matrix file:%s open failed.",cmStringNullGuard(fn));
  5152. goto errLabel;
  5153. }
  5154. if((rc = _cmBinMtxFileReadHdr(ctx,h,&rowCnt,&colCnt,&eleByteCnt,fn)) != cmOkRC )
  5155. goto errLabel;
  5156. if( mRowCnt != rowCnt )
  5157. rc = cmErrMsg(&err,cmArgAssertRC,"The binary matrix file row count and the return buffer row count are not the same.");
  5158. if( mColCnt != colCnt )
  5159. rc = cmErrMsg(&err,cmArgAssertRC,"The binary matrix file column count and the return buffer column count are not the same.");
  5160. if( mEleByteCnt != eleByteCnt )
  5161. rc = cmErrMsg(&err,cmArgAssertRC,"The binary matrix file element byte count and the return buffer element byte count are not the same.");
  5162. if( rc == cmOkRC )
  5163. {
  5164. rowBuf = cmMemAllocZ(char,colCnt*eleByteCnt);
  5165. for(i=0; i<rowCnt; ++i)
  5166. {
  5167. unsigned cn;
  5168. // read the row length
  5169. if( cmFileReadUInt(h,&cn,1) != kOkFileRC )
  5170. {
  5171. rc = cmErrMsg(&err,cmSubSysFailRC,"Error reading row length at row index:%i.",i);
  5172. goto errLabel;
  5173. }
  5174. if( colCntV != NULL )
  5175. colCntV[i] = cn;
  5176. // verify the actual col count does not exceed the max col count
  5177. if( cn > colCnt )
  5178. {
  5179. rc = cmErrMsg(&err,cmSubSysFailRC,"The actual column count:%i exceeds the max column count:%i.",cn,colCnt);
  5180. goto errLabel;
  5181. }
  5182. //read the row data
  5183. if( cmFileReadChar(h,rowBuf,cn*eleByteCnt) != kOkFileRC )
  5184. {
  5185. rc = cmErrMsg(&err,cmSubSysFailRC,"File read failed at row index:%i.",i);
  5186. goto errLabel;
  5187. }
  5188. char* dp = ((char*)retBuf) + i * eleByteCnt;
  5189. // the data is read in row-major order but the matrix must be
  5190. // returned on col major order - rearrange the columns here.
  5191. switch(eleByteCnt)
  5192. {
  5193. case sizeof(cmSample_t):
  5194. cmVOS_CopyN(((cmSample_t*)dp), cn, rowCnt, (cmSample_t*)rowBuf, 1 );
  5195. break;
  5196. case sizeof(cmReal_t):
  5197. cmVOR_CopyN(((cmReal_t*)dp), cn, rowCnt, (cmReal_t*)rowBuf, 1 );
  5198. break;
  5199. default:
  5200. rc = cmErrMsg(&err,cmSubSysFailRC,"Invalid element byte count:%i.",eleByteCnt);
  5201. goto errLabel;
  5202. }
  5203. }
  5204. }
  5205. errLabel:
  5206. cmMemPtrFree(&rowBuf);
  5207. cmFileClose(&h);
  5208. return rc;
  5209. }