libcm is a C development framework with an emphasis on audio signal processing applications.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cmProc.c 134KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250
  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 "cmFileSys.h"
  15. #include "cmProcObj.h"
  16. #include "cmProcTemplate.h"
  17. #include "cmAudioFile.h"
  18. #include "cmMath.h"
  19. #include "cmProc.h"
  20. #include "cmVectOps.h"
  21. #include "cmKeyboard.h"
  22. #include "cmGnuPlot.h"
  23. #include <time.h> // time()
  24. //------------------------------------------------------------------------------------------------------------
  25. void cmFloatPointExceptHandler( int signo, siginfo_t* info, void* context )
  26. {
  27. char* cp = "<Type Unknown>";
  28. switch( info->si_code )
  29. {
  30. case FPE_INTDIV: cp = "integer divide by zero"; break;
  31. case FPE_INTOVF: cp = "integer overflow"; break;
  32. case FPE_FLTDIV: cp = "divide by zero"; break;
  33. case FPE_FLTUND: cp = "underflow"; break;
  34. case FPE_FLTRES: cp = "inexact result"; break;
  35. case FPE_FLTINV: cp = "invalid operation"; break;
  36. case FPE_FLTSUB: cp = "subscript range error"; break;
  37. }
  38. fprintf(stderr,"Floating point exception: Type: %s\n",cp);
  39. exit(1);
  40. }
  41. // set 'orgSaPtr' to NULL to discard the current signal action state
  42. void cmSetupFloatPointExceptHandler( struct sigaction* orgSaPtr )
  43. {
  44. struct sigaction sa;
  45. sa.sa_handler = SIG_DFL;
  46. sa.sa_flags = SA_SIGINFO;
  47. sa.sa_sigaction = cmFloatPointExceptHandler;
  48. sigemptyset(&sa.sa_mask);
  49. // set all FP except flags excetp: FE_INEXACT
  50. #ifdef OS_OSX
  51. // we don't yet support FP exceptions on OSX
  52. // for an example of how to make this work with the linux interface as below
  53. // see: http://www-personal.umich.edu/~williams/archive/computation/fe-handling-example.c
  54. assert(0);
  55. #else
  56. // int flags = FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID;
  57. // feenableexcept(flags);
  58. assert(0);
  59. #endif
  60. sigaction( SIGFPE, &sa, orgSaPtr );
  61. }
  62. //------------------------------------------------------------------------------------------------------------
  63. cmAudioFileRd* cmAudioFileRdAlloc( cmCtx* c, cmAudioFileRd* p, unsigned procSmpCnt, const cmChar_t* fn, unsigned chIdx, unsigned begFrmIdx, unsigned endFrmIdx )
  64. {
  65. cmAudioFileRd* op = cmObjAlloc( cmAudioFileRd, c, p );
  66. if( fn != NULL )
  67. if( cmAudioFileRdOpen( op, procSmpCnt, fn, chIdx, begFrmIdx, endFrmIdx ) != cmOkRC )
  68. cmAudioFileRdFree(&op);
  69. return op;
  70. }
  71. cmRC_t cmAudioFileRdFree( cmAudioFileRd** pp )
  72. {
  73. cmRC_t rc = cmOkRC;
  74. if( pp != NULL && *pp != NULL )
  75. {
  76. cmAudioFileRd* p = *pp;
  77. if((rc = cmAudioFileRdClose(p)) == cmOkRC )
  78. {
  79. cmMemPtrFree(&p->outV);
  80. cmMemPtrFree(&p->fn);
  81. cmObjFree(pp);
  82. }
  83. }
  84. return rc;
  85. }
  86. cmRC_t cmAudioFileRdOpen( cmAudioFileRd* p, unsigned procSmpCnt, const cmChar_t* fn, unsigned chIdx, unsigned begFrmIdx, unsigned endFrmIdx )
  87. {
  88. cmRC_t rc;
  89. cmRC_t afRC;
  90. if((rc = cmAudioFileRdClose(p)) != cmOkRC )
  91. return rc;
  92. p->h = cmAudioFileNewOpen( fn, &p->info, &afRC, p->obj.err.rpt );
  93. if( afRC != kOkAfRC )
  94. return cmCtxRtCondition( &p->obj, afRC, "Unable to open the audio file:'%s'", fn );
  95. p->chIdx = chIdx;
  96. p->outN = endFrmIdx==cmInvalidIdx ? p->info.frameCnt : procSmpCnt;
  97. p->outV = cmMemResizeZ( cmSample_t, p->outV, p->outN );
  98. p->fn = cmMemResizeZ( cmChar_t, p->fn, strlen(fn)+1 );
  99. strcpy(p->fn,fn);
  100. //p->mfp = cmCtxAllocDebugFile( p->obj.ctx,"audioFile");
  101. p->lastReadFrmCnt = 0;
  102. p->eofFl = false;
  103. p->begFrmIdx = begFrmIdx;
  104. p->endFrmIdx = endFrmIdx==0 ? p->info.frameCnt : endFrmIdx;
  105. p->curFrmIdx = p->begFrmIdx;
  106. if( p->begFrmIdx > 0 )
  107. rc = cmAudioFileRdSeek(p,p->begFrmIdx);
  108. return rc;
  109. }
  110. cmRC_t cmAudioFileRdClose( cmAudioFileRd* p )
  111. {
  112. cmRC_t rc = cmOkRC;
  113. cmRC_t afRC;
  114. if( p == NULL )
  115. return cmOkRC;
  116. //cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  117. if( cmAudioFileIsOpen(p->h) == false )
  118. return cmOkRC;
  119. if((afRC = cmAudioFileDelete(&p->h)) != cmOkRC )
  120. rc = cmCtxRtCondition( &p->obj, afRC, "An attempt to close the audio file'%s' failed.", p->fn );
  121. return rc;
  122. }
  123. cmRC_t cmAudioFileRdRead( cmAudioFileRd* p )
  124. {
  125. cmRC_t rc = cmOkRC;
  126. cmRC_t afRC;
  127. if(p->eofFl || ((p->eofFl = cmAudioFileIsEOF(p->h)) == true) )
  128. return cmEofRC;
  129. unsigned n = p->endFrmIdx==cmInvalidIdx ? p->outN : cmMin( p->outN, p->endFrmIdx - p->curFrmIdx );
  130. if((afRC = cmAudioFileReadSample( p->h, n, p->chIdx, 1, &p->outV, &p->lastReadFrmCnt )) != kOkAfRC )
  131. rc = cmCtxRtCondition( &p->obj, afRC, "Audio file read failed on:'%s'.", p->fn);
  132. p->curFrmIdx += p->lastReadFrmCnt;
  133. if( n < p->outN )
  134. {
  135. cmVOS_Zero(p->outV + p->lastReadFrmCnt, p->outN - p->lastReadFrmCnt);
  136. p->eofFl = true;
  137. }
  138. if( p->mfp != NULL )
  139. cmMtxFileSmpExec( p->mfp, p->outV, p->outN );
  140. return rc;
  141. }
  142. cmRC_t cmAudioFileRdSeek( cmAudioFileRd* p, unsigned frmIdx )
  143. {
  144. cmRC_t rc = cmOkRC;
  145. cmRC_t afRC;
  146. if((afRC = cmAudioFileSeek( p->h, frmIdx )) != kOkAfRC )
  147. rc = cmCtxRtCondition( &p->obj, afRC, "Audio file read failed on:'%s'.", p->fn);
  148. return rc;
  149. }
  150. cmRC_t cmAudioFileRdMinMaxMean( cmAudioFileRd* p, unsigned chIdx, cmSample_t* minPtr, cmSample_t* maxPtr, cmSample_t* meanPtr )
  151. {
  152. cmRC_t rc = cmOkRC;
  153. cmRC_t afRC;
  154. if(( afRC = cmAudioFileMinMaxMean( p->h, chIdx, minPtr, maxPtr, meanPtr )) != kOkAfRC )
  155. rc = cmCtxRtCondition( &p->obj, afRC, "Audio file min, max, and mean calculation failed on '%s'", p->fn );
  156. return rc;
  157. }
  158. //------------------------------------------------------------------------------------------------------------
  159. cmShiftBuf* cmShiftBufAlloc( cmCtx* c, cmShiftBuf* p, unsigned procSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt )
  160. {
  161. cmShiftBuf* op = cmObjAlloc( cmShiftBuf, c, p );
  162. if( procSmpCnt > 0 && wndSmpCnt > 0 && hopSmpCnt > 0 )
  163. if( cmShiftBufInit(op, procSmpCnt, wndSmpCnt, hopSmpCnt ) != cmOkRC)
  164. cmShiftBufFree(&op);
  165. return op;
  166. }
  167. cmRC_t cmShiftBufFree( cmShiftBuf** pp )
  168. {
  169. cmRC_t rc = cmOkRC;
  170. if( pp != NULL && *pp != NULL )
  171. {
  172. if((rc = cmShiftBufFinal(*pp)) == cmOkRC )
  173. {
  174. cmMemPtrFree(&(*pp)->bufV);
  175. cmObjFree(pp);
  176. }
  177. }
  178. return rc;
  179. }
  180. cmRC_t cmShiftBufInit( cmShiftBuf* p, unsigned procSmpCnt, unsigned wndSmpCnt, unsigned hopSmpCnt )
  181. {
  182. cmRC_t rc;
  183. if( hopSmpCnt > wndSmpCnt )
  184. return cmCtxRtAssertFailed( &p->obj, cmArgAssertRC, "The window sample count (%i) must be greater than or equal to the hop sample count (%i).", wndSmpCnt, hopSmpCnt );
  185. if((rc = cmShiftBufFinal(p)) != cmOkRC )
  186. return rc;
  187. // The worst case storage requirement is where there are wndSmpCnt-1 samples in outV[] and procSmpCnt new samples arrive.
  188. p->bufSmpCnt = wndSmpCnt + procSmpCnt;
  189. p->bufV = cmMemResizeZ( cmSample_t, p->outV, p->bufSmpCnt );
  190. p->outV = p->bufV;
  191. p->outN = wndSmpCnt;
  192. p->wndSmpCnt = wndSmpCnt;
  193. p->procSmpCnt = procSmpCnt;
  194. p->hopSmpCnt = hopSmpCnt;
  195. p->inPtr = p->outV;
  196. p->fl = false;
  197. return cmOkRC;
  198. }
  199. cmRC_t cmShiftBufFinal( cmShiftBuf* p )
  200. {
  201. return cmOkRC;
  202. }
  203. // This function should be called in a loop until it returns false.
  204. // Note that 'sp' and 'sn' are ignored except p->fl == false.
  205. bool cmShiftBufExec( cmShiftBuf* p, const cmSample_t* sp, unsigned sn )
  206. {
  207. assert( sn <= p->procSmpCnt );
  208. // The active samples are in outV[wndSmpCnt]
  209. // Stored samples are between outV + wndSmpCnt and inPtr.
  210. // if the previous call to this function returned true then the buffer must be
  211. // shifted by hopSmpCnt samples - AND sp[] is ignored.
  212. if( p->fl )
  213. {
  214. // shift the output buffer to the left to remove expired samples
  215. p->outV += p->hopSmpCnt;
  216. // if there are not wndSmpCnt samples left in the buffer
  217. if( p->inPtr - p->outV < p->wndSmpCnt )
  218. {
  219. // then copy the remaining active samples (between outV and inPtr)
  220. // to the base of the physicalbuffer
  221. unsigned n = p->inPtr - p->outV;
  222. memmove( p->bufV, p->outV, n * sizeof(cmSample_t));
  223. p->inPtr = p->bufV + n; // update the input and output positions
  224. p->outV = p->bufV;
  225. }
  226. }
  227. else
  228. {
  229. // if the previous call to this function returned false then sp[sn] should not be ignored
  230. assert( p->inPtr + sn <= p->outV + p->bufSmpCnt );
  231. // copy the incoming samples into the buffer
  232. cmVOS_Copy(p->inPtr,sn,sp);
  233. p->inPtr += sn;
  234. }
  235. // if there are at least wndSmpCnt available samples in outV[]
  236. p->fl = p->inPtr - p->outV >= p->wndSmpCnt;
  237. return p->fl;
  238. }
  239. void cmShiftBufTest( cmCtx* c )
  240. {
  241. unsigned smpCnt = 48;
  242. unsigned procSmpCnt = 5;
  243. unsigned hopSmpCnt = 6;
  244. unsigned wndSmpCnt = 7;
  245. unsigned i;
  246. cmShiftBuf* b = cmShiftBufAlloc(c,NULL,procSmpCnt,wndSmpCnt,hopSmpCnt );
  247. cmSample_t x[ smpCnt ];
  248. cmVOS_Seq(x,smpCnt,1,1);
  249. //cmVOS_Print( rptFuncPtr, 1, smpCnt, x );
  250. for(i=0; i<smpCnt; i+=procSmpCnt)
  251. {
  252. while( cmShiftBufExec( b, x + i, procSmpCnt ) )
  253. {
  254. cmVOS_Print( c->obj.err.rpt, 1, wndSmpCnt, b->outV );
  255. }
  256. }
  257. cmShiftBufFree(&b);
  258. }
  259. /*
  260. bool cmShiftBufExec( cmShiftBuf* p, const cmSample_t* sp, unsigned sn )
  261. {
  262. bool retFl = false;
  263. if( sn > p->procSmpCnt )
  264. {
  265. cmCtxRtAssertFailed( p->obj.ctx, cmArgAssertRC, "The input sample count (%i) must be less than or equal to the proc sample count (%i).", sn, p->procSmpCnt);
  266. return false;
  267. }
  268. assert( sn <= p->procSmpCnt );
  269. cmSample_t* dbp = p->outV;
  270. cmSample_t* dep = p->outV + (p->outN - sn);
  271. cmSample_t* sbp = p->outV + sn;
  272. // shift the last bufCnt-shiftCnt samples over the first shiftCnt samples
  273. while( dbp < dep )
  274. *dbp++ = *sbp++;
  275. // copy in the new samples
  276. dbp = dep;
  277. dep = dbp + sn;
  278. while( dbp < dep )
  279. *dbp++ = *sp++;
  280. // if any space remains at the end of the buffer then zero it
  281. dep = p->outV + p->outN;
  282. while( dbp < dep )
  283. *dbp++ = 0;
  284. if( p->firstPtr > p->outV )
  285. p->firstPtr = cmMax( p->outV, p->firstPtr - p->procSmpCnt);
  286. p->curHopSmpCnt += sn;
  287. if( p->curHopSmpCnt >= p->hopSmpCnt )
  288. {
  289. p->curHopSmpCnt -= p->hopSmpCnt;
  290. retFl = true;
  291. }
  292. if( p->mfp != NULL )
  293. cmMtxFileSmpExec(p->mfp,p->outV,p->outN);
  294. return retFl;
  295. }
  296. */
  297. //------------------------------------------------------------------------------------------------------------
  298. cmWndFunc* cmWndFuncAlloc( cmCtx* c, cmWndFunc* p, unsigned wndId, unsigned wndSmpCnt, double kaiserSideLobeRejectDb )
  299. {
  300. cmWndFunc* op = cmObjAlloc( cmWndFunc, c, p );
  301. if( wndId != kInvalidWndId )
  302. if( cmWndFuncInit(op,wndId,wndSmpCnt,kaiserSideLobeRejectDb ) != cmOkRC )
  303. cmWndFuncFree(&op);
  304. return op;
  305. }
  306. cmRC_t cmWndFuncFree( cmWndFunc** pp )
  307. {
  308. cmRC_t rc = cmOkRC;
  309. if( pp != NULL && *pp != NULL )
  310. {
  311. cmWndFunc* p = *pp;
  312. if((rc = cmWndFuncFinal(p)) == cmOkRC )
  313. {
  314. cmMemPtrFree(&p->wndV);
  315. cmMemPtrFree(&p->outV);
  316. cmObjFree(pp);
  317. }
  318. }
  319. return rc;
  320. }
  321. cmRC_t cmWndFuncInit( cmWndFunc* p, unsigned wndId, unsigned wndSmpCnt, double kslRejectDb )
  322. {
  323. cmRC_t rc;
  324. if( wndId == (p->wndId | p->flags) && wndSmpCnt == p->outN && kslRejectDb == p->kslRejectDb )
  325. return cmOkRC;
  326. if((rc = cmWndFuncFinal(p)) != cmOkRC )
  327. return rc;
  328. p->wndV = cmMemResize( cmSample_t, p->wndV, wndSmpCnt );
  329. p->outV = cmMemResize( cmSample_t, p->outV, wndSmpCnt );
  330. p->outN = wndSmpCnt;
  331. p->wndId = wndId;
  332. p->kslRejectDb = kslRejectDb;
  333. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"wndFunc");
  334. p->flags = wndId & (~kWndIdMask);
  335. switch( wndId & kWndIdMask )
  336. {
  337. case kHannWndId: cmVOS_Hann( p->wndV, p->outN ); break;
  338. case kHannMatlabWndId: cmVOS_HannMatlab( p->wndV, p->outN ); break;
  339. case kHammingWndId: cmVOS_Hamming( p->wndV, p->outN ); break;
  340. case kTriangleWndId: cmVOS_Triangle( p->wndV, p->outN ); break;
  341. case kUnityWndId: cmVOS_Fill( p->wndV, p->outN, 1.0 ); break;
  342. case kKaiserWndId:
  343. {
  344. double beta;
  345. if( cmIsFlag(wndId,kSlRejIsBetaWndFl) )
  346. beta = kslRejectDb;
  347. else
  348. beta = cmVOS_KaiserBetaFromSidelobeReject(fabs(kslRejectDb));
  349. cmVOS_Kaiser( p->wndV,p->outN, beta);
  350. }
  351. break;
  352. case kInvalidWndId: break;
  353. default:
  354. { assert(0); }
  355. }
  356. cmSample_t den = 0;
  357. cmSample_t num = 1;
  358. if( cmIsFlag(p->flags,kNormBySumWndFl) )
  359. {
  360. den = cmVOS_Sum(p->wndV, p->outN);
  361. num = wndSmpCnt;
  362. }
  363. if( cmIsFlag(p->flags,kNormByLengthWndFl) )
  364. den += wndSmpCnt;
  365. if( den > 0 )
  366. {
  367. cmVOS_MultVS(p->wndV,p->outN,num);
  368. cmVOS_DivVS(p->wndV,p->outN,den);
  369. }
  370. return cmOkRC;
  371. }
  372. cmRC_t cmWndFuncFinal( cmWndFunc* p )
  373. {
  374. //if( p != NULL )
  375. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  376. return cmOkRC;
  377. }
  378. cmRC_t cmWndFuncExec( cmWndFunc* p, const cmSample_t* sp, unsigned sn )
  379. {
  380. if( sn > p->outN )
  381. return cmCtxRtAssertFailed( &p->obj, cmArgAssertRC, "The length of the input vector (%i) is greater thean the length of the window function (%i).", sn, p->outN );
  382. if( p->wndId != kInvalidWndId )
  383. cmVOS_MultVVV( p->outV, sn, sp, p->wndV );
  384. if( p->mfp != NULL )
  385. cmMtxFileSmpExec(p->mfp,p->outV,p->outN);
  386. return cmOkRC;
  387. }
  388. void cmWndFuncTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  389. {
  390. unsigned wndCnt = 5;
  391. double kaiserSideLobeRejectDb = 30;
  392. cmCtx c;
  393. cmCtxAlloc(&c,rpt,lhH,stH);
  394. cmWndFunc* p = cmWndFuncAlloc(&c,NULL,kHannWndId,wndCnt, 0 );
  395. cmVOS_Print( rpt, 1, wndCnt, p->wndV );
  396. cmWndFuncInit(p,kHammingWndId ,wndCnt, 0 );
  397. cmVOS_Print( rpt, 1, wndCnt, p->wndV );
  398. cmWndFuncInit(p,kTriangleWndId ,wndCnt, 0 );
  399. cmVOS_Print( rpt, 1, wndCnt, p->wndV );
  400. cmWndFuncInit(p,kKaiserWndId ,wndCnt, kaiserSideLobeRejectDb );
  401. cmVOS_Print( rpt, 1, wndCnt, p->wndV );
  402. cmSample_t wV[ wndCnt ];
  403. cmVOS_HannMatlab(wV,wndCnt);
  404. cmVOS_Print( rpt, 1, wndCnt, wV);
  405. cmWndFuncFree(&p);
  406. }
  407. //------------------------------------------------------------------------------------------------------------
  408. cmSpecDelay* cmSpecDelayAlloc( cmCtx* c, cmSpecDelay* ap, unsigned maxDelayCnt, unsigned binCnt )
  409. {
  410. cmSpecDelay* p = cmObjAlloc( cmSpecDelay, c, ap );
  411. if( maxDelayCnt > 0 && binCnt > 0 )
  412. if( cmSpecDelayInit(p,maxDelayCnt,binCnt) != cmOkRC )
  413. cmSpecDelayFree(&p);
  414. return p;
  415. }
  416. cmRC_t cmSpecDelayFree( cmSpecDelay** pp )
  417. {
  418. cmRC_t rc = cmOkRC;
  419. if( pp != NULL && *pp != NULL )
  420. {
  421. cmSpecDelay* p = *pp;
  422. if((rc=cmSpecDelayFinal(p)) == cmOkRC )
  423. {
  424. cmMemPtrFree(&p->bufPtr);
  425. cmObjFree(pp);
  426. }
  427. }
  428. return rc;
  429. }
  430. cmRC_t cmSpecDelayInit( cmSpecDelay* p, unsigned maxDelayCnt, unsigned binCnt )
  431. {
  432. cmRC_t rc;
  433. if((rc = cmSpecDelayFinal(p)) != cmOkRC )
  434. return rc;
  435. p->bufPtr = cmMemResizeZ( cmSample_t, p->bufPtr, binCnt * maxDelayCnt );
  436. p->maxDelayCnt = maxDelayCnt;
  437. p->outN = binCnt;
  438. p->inIdx = 0;
  439. return cmOkRC;
  440. }
  441. cmRC_t cmSpecDelayFinal(cmSpecDelay* p )
  442. { return cmOkRC; }
  443. cmRC_t cmSpecDelayExec( cmSpecDelay* p, const cmSample_t* sp, unsigned sn )
  444. {
  445. cmSample_t* dp = p->bufPtr + (p->inIdx * p->outN);
  446. cmVOS_Copy( dp, cmMin(sn,p->outN), sp);
  447. p->inIdx = (p->inIdx+1) % p->maxDelayCnt;
  448. return cmOkRC;
  449. }
  450. const cmSample_t* cmSpecDelayOutPtr( cmSpecDelay* p, unsigned delayCnt )
  451. {
  452. assert( delayCnt < p->maxDelayCnt );
  453. int i = p->inIdx - delayCnt;
  454. if( i < 0 )
  455. i = p->maxDelayCnt + i;
  456. return p->bufPtr + (i * p->outN);
  457. }
  458. //------------------------------------------------------------------------------------------------------------
  459. cmFilter* cmFilterAlloc( cmCtx* c, cmFilter* ap, const cmReal_t* b, unsigned bn, const cmReal_t* a, unsigned an, unsigned procSmpCnt, const cmReal_t* d )
  460. {
  461. cmRC_t rc;
  462. cmFilter* p = cmObjAlloc(cmFilter,c,ap);
  463. if( (bn > 0 || an > 0) && procSmpCnt > 0 )
  464. if( (rc = cmFilterInit( p, b, bn, a, an, procSmpCnt, d)) != cmOkRC )
  465. cmFilterFree(&p);
  466. return p;
  467. }
  468. cmFilter* cmFilterAllocEllip( cmCtx* c, cmFilter* ap, cmReal_t srate, cmReal_t passHz, cmReal_t stopHz, cmReal_t passDb, cmReal_t stopDb, unsigned procSmpCnt, const cmReal_t* d )
  469. {
  470. cmRC_t rc;
  471. cmFilter* p = cmObjAlloc(cmFilter,c,ap);
  472. if( srate > 0 && passHz > 0 && procSmpCnt > 0 )
  473. if( (rc = cmFilterInitEllip( p, srate, passHz, stopHz, passDb, stopDb, procSmpCnt, d)) != cmOkRC )
  474. cmFilterFree(&p);
  475. return p;
  476. }
  477. cmRC_t cmFilterFree( cmFilter** pp )
  478. {
  479. cmRC_t rc = cmOkRC;
  480. if( pp != NULL && *pp != NULL )
  481. {
  482. cmFilter* p = *pp;
  483. if((rc = cmFilterFinal(p)) == cmOkRC )
  484. {
  485. cmMemPtrFree(&p->a);
  486. cmMemPtrFree(&p->b);
  487. cmMemPtrFree(&p->d);
  488. cmMemPtrFree(&p->outSmpV);
  489. cmObjFree(pp);
  490. }
  491. }
  492. return rc;
  493. }
  494. cmRC_t cmFilterInit( cmFilter* p, const cmReal_t* b, unsigned bn, const cmReal_t* a, unsigned an, unsigned procSmpCnt, const cmReal_t* d )
  495. {
  496. assert( bn >= 1 );
  497. assert( an >= 1 && a[0] != 0 );
  498. cmRC_t rc;
  499. if((rc = cmFilterFinal(p)) != cmOkRC )
  500. return rc;
  501. int cn = cmMax(an,bn) - 1;
  502. // The output vector may be used as either cmReal_t or cmSample_t.
  503. // Find the larger of the two possible types.
  504. if( sizeof(cmReal_t) > sizeof(cmSample_t) )
  505. {
  506. p->outRealV = cmMemResizeZ( cmReal_t, p->outRealV, procSmpCnt );
  507. p->outSmpV = (cmSample_t*)p->outRealV;
  508. }
  509. else
  510. {
  511. p->outSmpV = cmMemResizeZ( cmSample_t, p->outSmpV, procSmpCnt );
  512. p->outRealV = (cmReal_t*)p->outRealV;
  513. }
  514. p->a = cmMemResizeZ( cmReal_t, p->a, cn );
  515. p->b = cmMemResizeZ( cmReal_t, p->b, cn );
  516. p->d = cmMemResizeZ( cmReal_t, p->d, cn+1 );
  517. //p->outV = cmMemResizeZ( cmSample_t, p->outV, procSmpCnt );
  518. p->outN = procSmpCnt;
  519. p->an = an;
  520. p->bn = bn;
  521. p->cn = cn;
  522. p->di = 0;
  523. p->b0 = b[0] / a[0];
  524. int i;
  525. for(i=0; i<an-1; ++i)
  526. p->a[i] = a[i+1] / a[0];
  527. for(i=0; i<bn-1; ++i)
  528. p->b[i] = b[i+1] / a[0];
  529. if( d != NULL )
  530. cmVOR_Copy(p->d,cn,d);
  531. return cmOkRC;
  532. }
  533. // initialize an elliptic lowpass filter with the given characteristics
  534. // ref: Parks & Burrus, Digital Filter Design, sec. 7.2.7 - 7.2.8
  535. cmRC_t cmFilterInitEllip( cmFilter* p, cmReal_t srate, cmReal_t passHz, cmReal_t stopHz, cmReal_t passDb, cmReal_t stopDb, unsigned procSmpCnt, const cmReal_t* d )
  536. {
  537. assert( srate > 0 );
  538. assert( passHz > 0 && stopHz > passHz && srate/2 > stopHz );
  539. cmReal_t Wp, Ws, ep, v0,
  540. k, kc, k1, k1c,
  541. K, Kc, K1, K1c,
  542. sn, cn, dn,
  543. sm, cm, dm,
  544. zr, zi, pr, pi;
  545. unsigned N, L, j;
  546. // prewarp Wp and Ws, calculate k
  547. Wp = 2 * srate * tan(M_PI * passHz / srate);
  548. Ws = 2 * srate * tan(M_PI * stopHz / srate);
  549. k = Wp / Ws;
  550. // calculate ep and k1 from passDb and stopDb
  551. ep = sqrt(pow(10, passDb/10) - 1);
  552. k1 = ep / sqrt(pow(10, stopDb/10) - 1);
  553. // calculate complimentary moduli
  554. kc = sqrt(1-k*k);
  555. k1c = sqrt(1-k1*k1);
  556. // calculate complete elliptic integrals
  557. K = cmEllipK( kc );
  558. Kc = cmEllipK( k );
  559. K1 = cmEllipK( k1c );
  560. K1c = cmEllipK( k1 );
  561. // calculate minimum integer filter order N
  562. N = ceil(K*K1c/Kc/K1);
  563. // recalculate k and kc from chosen N
  564. // Ws is minimized while other specs held constant
  565. k = cmEllipDeg( K1c/K1/N );
  566. kc = sqrt(1-k*k);
  567. K = cmEllipK( kc );
  568. Kc = cmEllipK( k );
  569. Ws = Wp / k;
  570. // initialize temporary coefficient arrays
  571. cmReal_t b[N+1], a[N+1];
  572. a[0] = b[0] = 1;
  573. memset(b+1, 0, N*sizeof(cmReal_t));
  574. memset(a+1, 0, N*sizeof(cmReal_t));
  575. // intermediate value needed for determining poles
  576. v0 = K/K1/N * cmEllipArcSc( 1/ep, k1 );
  577. cmEllipJ( v0, k, &sm, &cm, &dm );
  578. for( L=1-N%2; L<N; L+=2 )
  579. {
  580. // find the next pole and zero on s-plane
  581. cmEllipJ( K*L/N, kc, &sn, &cn, &dn );
  582. zr = 0;
  583. zi = L ? Ws/sn : 1E25;
  584. pr = -Wp*sm*cm*cn*dn/(1-pow(dn*sm,2));
  585. pi = Wp*dm*sn/(1-pow(dn*sm,2));
  586. // convert pole and zero to z-plane using bilinear transform
  587. cmBlt( 1, srate, &zr, &zi );
  588. cmBlt( 1, srate, &pr, &pi );
  589. if( L == 0 )
  590. {
  591. // first order section
  592. b[1] = -zr;
  593. a[1] = -pr;
  594. }
  595. else
  596. {
  597. // replace complex root and its conjugate with 2nd order section
  598. zi = zr*zr + zi*zi;
  599. zr *= -2;
  600. pi = pr*pr + pi*pi;
  601. pr *= -2;
  602. // combine with previous sections to obtain filter coefficients
  603. for( j = L+1; j >= 2; j-- )
  604. {
  605. b[j] = b[j] + zr*b[j-1] + zi*b[j-2];
  606. a[j] = a[j] + pr*a[j-1] + pi*a[j-2];
  607. }
  608. b[1] += zr;
  609. a[1] += pr;
  610. }
  611. }
  612. // scale b coefficients s.t. DC gain is 0 dB
  613. cmReal_t sumB = 0, sumA = 0;
  614. for( j = 0; j < N+1; j++ )
  615. {
  616. sumB += b[j];
  617. sumA += a[j];
  618. }
  619. sumA /= sumB;
  620. for( j = 0; j < N+1; j++ )
  621. b[j] *= sumA;
  622. return cmFilterInit( p, b, N+1, a, N+1, procSmpCnt, d );
  623. }
  624. cmRC_t cmFilterFinal( cmFilter* p )
  625. { return cmOkRC; }
  626. cmRC_t cmFilterExecS( cmFilter* p, const cmSample_t* x, unsigned xn, cmSample_t* yy, unsigned yn )
  627. {
  628. cmSample_t* y;
  629. if( yy == NULL || yn==0 )
  630. {
  631. y = p->outSmpV;
  632. yn = p->outN;
  633. }
  634. else
  635. {
  636. y = yy;
  637. }
  638. cmVOS_Filter( y, yn, x, xn, p->b0, p->b, p->a, p->d, p->cn );
  639. return cmOkRC;
  640. /*
  641. int i,j;
  642. cmSample_t y0 = 0;
  643. cmSample_t* y;
  644. unsigned n;
  645. if( yy == NULL || yn==0 )
  646. {
  647. n = cmMin(p->outN,xn);
  648. y = p->outSmpV;
  649. yn = p->outN;
  650. }
  651. else
  652. {
  653. n = cmMin(yn,xn);
  654. y = yy;
  655. }
  656. // This is a direct form II algorithm based on the MATLAB implmentation
  657. // http://www.mathworks.com/access/helpdesk/help/techdoc/ref/filter.html#f83-1015962
  658. for(i=0; i<n; ++i)
  659. {
  660. //cmSample_t x0 = x[i];
  661. y[i] = (x[i] * p->b0) + p->d[0];
  662. y0 = y[i];
  663. for(j=0; j<p->cn; ++j)
  664. p->d[j] = (p->b[j] * x[i]) - (p->a[j] * y0) + p->d[j+1];
  665. }
  666. // if fewer input samples than output samples - zero the end of the output buffer
  667. if( yn > xn )
  668. cmVOS_Fill(y+i,yn-i,0);
  669. return cmOkRC;
  670. */
  671. }
  672. cmRC_t cmFilterExecR( cmFilter* p, const cmReal_t* x, unsigned xn, cmReal_t* yy, unsigned yn )
  673. {
  674. cmReal_t* y;
  675. if( yy == NULL || yn==0 )
  676. {
  677. y = p->outRealV;
  678. yn = p->outN;
  679. }
  680. else
  681. {
  682. //n = cmMin(yn,xn);
  683. y = yy;
  684. }
  685. cmVOR_Filter( y, yn, x, xn, p->b0, p->b, p->a, p->d, p->cn );
  686. return cmOkRC;
  687. }
  688. cmRC_t cmFilterSignal( cmCtx* c, const cmReal_t b[], unsigned bn, const cmReal_t a[], unsigned an, const cmSample_t* x, unsigned xn, cmSample_t* y, unsigned yn )
  689. {
  690. int procSmpCnt = cmMin(1024,xn);
  691. cmFilter* p = cmFilterAlloc(c,NULL,b,bn,a,an,procSmpCnt,NULL);
  692. int i,n;
  693. for(i=0; i<xn && i<yn; i+=n)
  694. {
  695. n = cmMin(procSmpCnt,cmMin(yn-i,xn-i));
  696. cmFilterExecS(p,x+i,n,y+i,n);
  697. }
  698. if( i < yn )
  699. cmVOS_Fill(y+i,yn-i,0);
  700. cmFilterFree(&p);
  701. return cmOkRC;
  702. }
  703. cmRC_t cmFilterFilterS(cmCtx* c, const cmReal_t bb[], unsigned bn, const cmReal_t aa[], unsigned an, const cmSample_t* x, unsigned xn, cmSample_t* y, unsigned yn )
  704. {
  705. cmFilter* f = cmFilterAlloc(c,NULL,NULL,0,NULL,0,0,NULL);
  706. cmVOS_FilterFilter( f, cmFilterExecS, bb,bn,aa,an,x,xn,y,yn);
  707. cmFilterFree(&f);
  708. return cmOkRC;
  709. }
  710. cmRC_t cmFilterFilterR(cmCtx* c, const cmReal_t bb[], unsigned bn, const cmReal_t aa[], unsigned an, const cmReal_t* x, unsigned xn, cmReal_t* y, unsigned yn )
  711. {
  712. cmFilter* f = cmFilterAlloc(c,NULL,NULL,0,NULL,0,0,NULL);
  713. cmVOR_FilterFilter( f, cmFilterExecR, bb,bn,aa,an,x,xn,y,yn);
  714. cmFilterFree(&f);
  715. return cmOkRC;
  716. }
  717. void cmFilterTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  718. {
  719. cmCtx c;
  720. cmCtxAlloc(&c, rpt, lhH, stH );
  721. cmReal_t b[] = { 0.16, 0.32, 0.16 };
  722. unsigned bn = sizeof(b)/sizeof(cmReal_t);
  723. cmReal_t a[] = {1 , -.5949, .2348 };
  724. unsigned an = sizeof(a)/sizeof(cmReal_t);
  725. cmReal_t x[] = { 1,0,0,0,1,0,0,0 };
  726. unsigned xn = sizeof(x)/sizeof(cmReal_t);
  727. cmReal_t d[] = { .5, -.25};
  728. // 0.1600 0.4152 0.3694 0.1223 0.1460 0.3781 0.3507 0.1198
  729. // -0.0111 -0.0281
  730. cmFilter* p = cmFilterAlloc(&c,NULL,b,bn,a,an,xn,d);
  731. cmFilterExecR(p,x,xn,NULL,0);
  732. cmVOR_Print( rpt, 1, xn, p->outRealV );
  733. cmVOR_Print( rpt, 1, p->cn, p->d );
  734. cmFilterFree(&p);
  735. cmObjFreeStatic( cmCtxFree, cmCtx, c );
  736. /*
  737. cmReal_t b[] = { 0.16, 0.32, 0.16 };
  738. unsigned bn = sizeof(b)/sizeof(cmReal_t);
  739. cmReal_t a[] = { 1, -.5949, .2348};
  740. unsigned an = sizeof(a)/sizeof(cmReal_t);
  741. cmSample_t x[] = { 1,0,0,0,0,0,0,0,0,0 };
  742. unsigned xn = sizeof(x)/sizeof(cmSample_t);
  743. cmFilter* p = cmFilterAlloc(&c,NULL,b,bn,a,an,xn);
  744. cmFilterExec(&c,p,x,xn,NULL,0);
  745. cmVOS_Print( vReportFunc, 1, xn, p->outV );
  746. cmVOR_Print( vReportFunc, 1, p->cn, p->d );
  747. cmFilterExec(&c,p,x,xn,NULL,0);
  748. cmVOS_Print( vReportFunc, 1, xn, p->outV );
  749. cmFilterFree(&p);
  750. */
  751. }
  752. void cmFilterFilterTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  753. {
  754. cmCtx c;
  755. cmCtxAlloc(&c, rpt, lhH, stH );
  756. cmReal_t b[] = { 0.36, 0.32, 0.36 };
  757. unsigned bn = sizeof(b)/sizeof(cmReal_t);
  758. cmReal_t a[] = {1 , -.5949, .2348 };
  759. unsigned an = sizeof(a)/sizeof(cmReal_t);
  760. cmReal_t x[] = { 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0 };
  761. unsigned xn = sizeof(x)/sizeof(cmReal_t);
  762. unsigned yn = xn;
  763. cmReal_t y[yn];
  764. memset(y,0,sizeof(y));
  765. cmFilterFilterR(&c, b,bn,a,an,x,xn,y,yn );
  766. cmVOR_Print( rpt, 1, yn, y );
  767. cmObjFreeStatic( cmCtxFree, cmCtx, c );
  768. }
  769. //------------------------------------------------------------------------------------------------------------
  770. cmComplexDetect* cmComplexDetectAlloc(cmCtx* c, cmComplexDetect* p, unsigned binCnt )
  771. {
  772. cmComplexDetect* op = cmObjAlloc( cmComplexDetect, c, p );
  773. cmSpecDelayAlloc(c,&op->phsDelay,0,0);
  774. cmSpecDelayAlloc(c,&op->magDelay,0,0);
  775. if( binCnt > 0 )
  776. if( cmComplexDetectInit(op,binCnt) != cmOkRC && p == NULL )
  777. cmComplexDetectFree(&op);
  778. return op;
  779. }
  780. cmRC_t cmComplexDetectFree( cmComplexDetect** pp )
  781. {
  782. cmRC_t rc;
  783. if( pp != NULL && *pp != NULL )
  784. {
  785. cmComplexDetect* p = *pp;
  786. if((rc = cmComplexDetectFinal(p)) == cmOkRC )
  787. {
  788. cmSpecDelay* sdp;
  789. sdp = &p->phsDelay;
  790. cmSpecDelayFree(&sdp);
  791. sdp = &p->magDelay;
  792. cmSpecDelayFree(&sdp);
  793. cmObjFree(pp);
  794. }
  795. }
  796. return cmOkRC;
  797. }
  798. cmRC_t cmComplexDetectInit( cmComplexDetect* p, unsigned binCnt )
  799. {
  800. cmRC_t rc;
  801. if((rc = cmComplexDetectFinal(p)) != cmOkRC )
  802. return rc;
  803. cmSpecDelayInit(&p->phsDelay,2,binCnt);
  804. cmSpecDelayInit(&p->magDelay,1,binCnt);
  805. p->binCnt = binCnt;
  806. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"complexDetect");
  807. //p->cdfSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kCDF_FId, 1 );
  808. return cmOkRC;
  809. }
  810. cmRC_t cmComplexDetectFinal( cmComplexDetect* p)
  811. {
  812. //if( p != NULL )
  813. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  814. return cmOkRC;
  815. }
  816. cmRC_t cmComplexDetectExec( cmComplexDetect* p, const cmSample_t* magV, const cmSample_t* phsV, unsigned binCnt )
  817. {
  818. p->out = cmVOS_ComplexDetect( magV, cmSpecDelayOutPtr(&p->magDelay,0), phsV, cmSpecDelayOutPtr(&p->phsDelay,1), cmSpecDelayOutPtr(&p->phsDelay,0), binCnt);
  819. p->out /= 10000000;
  820. cmSpecDelayExec(&p->magDelay,magV,binCnt);
  821. cmSpecDelayExec(&p->phsDelay,phsV,binCnt);
  822. //if( p->mfp != NULL )
  823. // cmMtxFileSmpExec( p->mfp, &p->out, 1 );
  824. return cmOkRC;
  825. }
  826. //------------------------------------------------------------------------------------------------------------
  827. cmSample_t _cmComplexOnsetMedian( const cmSample_t* sp, unsigned sn, void* userPtr )
  828. { return cmVOS_Median(sp,sn); }
  829. cmComplexOnset* cmComplexOnsetAlloc( cmCtx* c, cmComplexOnset* p, unsigned procSmpCnt, double srate, unsigned medFiltWndSmpCnt, double threshold, unsigned frameCnt )
  830. {
  831. cmComplexOnset* op = cmObjAlloc( cmComplexOnset, c, p );
  832. if( procSmpCnt > 0 && srate > 0 && medFiltWndSmpCnt > 0 )
  833. if( cmComplexOnsetInit( op, procSmpCnt, srate, medFiltWndSmpCnt, threshold, frameCnt ) != cmOkRC )
  834. cmComplexOnsetFree(&op);
  835. return op;
  836. }
  837. cmRC_t cmComplexOnsetFree( cmComplexOnset** pp)
  838. {
  839. cmRC_t rc = cmOkRC;
  840. cmComplexOnset* p = *pp;
  841. if( pp==NULL || *pp == NULL )
  842. return cmOkRC;
  843. if((rc = cmComplexOnsetFinal(*pp)) != cmOkRC )
  844. return rc;
  845. cmMemPtrFree(&p->df);
  846. cmMemPtrFree(&p->fdf);
  847. cmObjFree(pp);
  848. return cmOkRC;
  849. }
  850. cmRC_t cmComplexOnsetInit( cmComplexOnset* p, unsigned procSmpCnt, double srate, unsigned medFiltWndSmpCnt, double threshold, unsigned frameCnt )
  851. {
  852. cmRC_t rc;
  853. if(( rc = cmComplexOnsetFinal(p)) != cmOkRC )
  854. return rc;
  855. p->frmCnt = frameCnt;
  856. p->dfi = 0;
  857. p->df = cmMemResizeZ( cmSample_t, p->df, frameCnt );
  858. p->fdf = cmMemResizeZ( cmSample_t, p->fdf, frameCnt );
  859. p->onrate = 0;
  860. p->threshold = threshold;
  861. p->medSmpCnt = medFiltWndSmpCnt;
  862. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"complexOnset");
  863. return cmOkRC;
  864. }
  865. cmRC_t cmComplexOnsetFinal( cmComplexOnset* p)
  866. {
  867. //if( p != NULL )
  868. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  869. return cmOkRC;
  870. }
  871. cmRC_t cmComplexOnsetExec( cmComplexOnset* p, cmSample_t cdf )
  872. {
  873. p->df[p->dfi++] = cdf;
  874. return cmOkRC;
  875. }
  876. cmRC_t cmComplexOnsetCalc( cmComplexOnset* p )
  877. {
  878. // df -= mean(df)
  879. cmVOS_SubVS(p->df,p->frmCnt,cmVOS_Mean(p->df,p->frmCnt));
  880. // low pass forward/backward filter df[] into fdf[]
  881. double d = 2 + sqrt(2);
  882. cmReal_t b[] = {1/d, 2/d, 1/d};
  883. unsigned bn = sizeof(b)/sizeof(b[0]);
  884. cmReal_t a[] = {1, 0, 7-2*d};
  885. unsigned an = sizeof(a)/sizeof(a[0]);
  886. cmFilterFilterS(p->obj.ctx,b,bn,a,an,p->df,p->frmCnt,p->fdf,p->frmCnt);
  887. // median filter to low-passed filtered fdf[] into df[]
  888. cmVOS_FnThresh(p->fdf,p->frmCnt,p->medSmpCnt,p->df,1,NULL);
  889. // subtract med filtered signal from the low passed signal.
  890. // fdf[] -= df[];
  891. cmVOS_SubVV(p->fdf,p->frmCnt,p->df);
  892. cmVOS_SubVS(p->fdf,p->frmCnt,p->threshold);
  893. cmSample_t *bp = p->df,
  894. *ep = bp + p->frmCnt - 1,
  895. *dp = p->fdf + 1;
  896. *bp++ = *ep = 0;
  897. for( ; bp<ep; bp++,dp++)
  898. {
  899. *bp = (*dp > *(dp-1) && *dp > *(dp+1) && *dp > 0) ? 1 : 0;
  900. p->onrate += *bp;
  901. }
  902. p->onrate /= p->frmCnt;
  903. /*
  904. if( p->mfp != NULL )
  905. {
  906. bp = p->df;
  907. ep = bp + p->frmCnt;
  908. while( bp < ep )
  909. cmMtxFileSmpExec( p->mfp, bp++, 1 );
  910. }
  911. */
  912. return cmOkRC;
  913. }
  914. //------------------------------------------------------------------------------------------------------------
  915. cmMfcc* cmMfccAlloc( cmCtx* c, cmMfcc* ap, double srate, unsigned melBandCnt, unsigned dctCoeffCnt, unsigned binCnt )
  916. {
  917. cmMfcc* p = cmObjAlloc( cmMfcc, c, ap );
  918. if( melBandCnt > 0 && binCnt > 0 && dctCoeffCnt > 0 )
  919. if( cmMfccInit( p, srate, melBandCnt, dctCoeffCnt, binCnt ) != cmOkRC )
  920. cmMfccFree(&p);
  921. return p;
  922. }
  923. cmRC_t cmMfccFree( cmMfcc** pp )
  924. {
  925. cmRC_t rc = cmOkRC;
  926. if( pp==NULL || *pp == NULL )
  927. return cmOkRC;
  928. cmMfcc* p = *pp;
  929. if( (rc = cmMfccFinal(p)) != cmOkRC )
  930. return rc;
  931. cmMemPtrFree(&p->melM);
  932. cmMemPtrFree(&p->dctM);
  933. cmMemPtrFree(&p->outV);
  934. cmObjFree(pp);
  935. return rc;
  936. }
  937. cmRC_t cmMfccInit( cmMfcc* p, double srate, unsigned melBandCnt, unsigned dctCoeffCnt, unsigned binCnt )
  938. {
  939. cmRC_t rc;
  940. if((rc = cmMfccFinal(p)) != cmOkRC )
  941. return rc;
  942. p->melM = cmMemResize( cmReal_t, p->melM, melBandCnt * binCnt );
  943. p->dctM = cmMemResize( cmReal_t, p->dctM, dctCoeffCnt * melBandCnt );
  944. p->outV = cmMemResize( cmReal_t, p->outV, dctCoeffCnt );
  945. // each row of the matrix melp contains a mask
  946. cmVOR_MelMask( p->melM, melBandCnt, binCnt, srate, kShiftMelFl );
  947. // each row contains melBandCnt elements
  948. cmVOR_DctMatrix(p->dctM, dctCoeffCnt, melBandCnt );
  949. p->melBandCnt = melBandCnt;
  950. p->dctCoeffCnt = dctCoeffCnt;
  951. p->binCnt = binCnt;
  952. p->outN = dctCoeffCnt;
  953. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"mfcc");
  954. //if( p->obj.ctx->statsProcPtr != NULL )
  955. // p->mfccSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kMFCC_FId, p->outN );
  956. return cmOkRC;
  957. }
  958. cmRC_t cmMfccFinal( cmMfcc* p )
  959. {
  960. //if( p != NULL )
  961. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  962. return cmOkRC;
  963. }
  964. cmRC_t cmMfccExecPower( cmMfcc* p, const cmReal_t* magPowV, unsigned binCnt )
  965. {
  966. assert( binCnt == p->binCnt );
  967. cmReal_t t[ p->melBandCnt ];
  968. // apply the mel filter mask to the power spectrum
  969. cmVOR_MultVMV( t, p->melBandCnt, p->melM, binCnt, magPowV );
  970. // convert mel bands to dB
  971. cmVOR_PowerToDb( t, p->melBandCnt, t );
  972. // decorellate the bands with a DCT
  973. cmVOR_MultVMV( p->outV, p->dctCoeffCnt, p->dctM, p->melBandCnt, t );
  974. /*
  975. cmPlotSelectSubPlot(0,0);
  976. cmPlotClear();
  977. //cmPlotLineS( "power", NULL, magPowV, NULL, 35, NULL, kSolidPlotLineId );
  978. cmPlotLineS( "mel", NULL, t0, NULL, p->melBandCnt, NULL, kSolidPlotLineId );
  979. cmPlotSelectSubPlot(1,0);
  980. cmPlotClear();
  981. //cmPlotLineS( "meldb", NULL, t1, NULL, p->melBandCnt, NULL, kSolidPlotLineId );
  982. cmPlotLineS( "mfcc", NULL, p->outV+1, NULL, p->dctCoeffCnt-1, NULL, kSolidPlotLineId );
  983. */
  984. if( p->mfp != NULL )
  985. cmMtxFileRealExec(p->mfp,p->outV, p->outN);
  986. return cmOkRC;
  987. }
  988. cmRC_t cmMfccExecAmplitude( cmMfcc* p, const cmReal_t* magAmpV, unsigned binCnt )
  989. {
  990. cmReal_t t[ binCnt ];
  991. cmVOR_MultVVV( t,binCnt, magAmpV, magAmpV );
  992. cmMfccExecPower(p,t,binCnt);
  993. if( p->mfp != NULL )
  994. cmMtxFileRealExec(p->mfp,p->outV, p->outN);
  995. return cmOkRC;
  996. }
  997. //------------------------------------------------------------------------------------------------------------
  998. enum { cmSonesEqlConBinCnt = kEqualLoudBandCnt, cmSonesEqlConCnt=13 };
  999. cmSones* cmSonesAlloc( cmCtx* c, cmSones* ap, double srate, unsigned barkBandCnt, unsigned binCnt, unsigned flags )
  1000. {
  1001. cmSones* p = cmObjAlloc( cmSones, c, ap );
  1002. if( srate > 0 && barkBandCnt > 0 && binCnt > 0 )
  1003. if( cmSonesInit(p,srate,barkBandCnt,binCnt,flags) != cmOkRC )
  1004. cmSonesFree(&p);
  1005. return p;
  1006. }
  1007. cmRC_t cmSonesFree( cmSones** pp )
  1008. {
  1009. cmRC_t rc = cmOkRC;
  1010. cmSones* p = *pp;
  1011. if( pp==NULL || *pp==NULL)
  1012. return cmOkRC;
  1013. if((rc = cmSonesFinal(p)) != cmOkRC )
  1014. return rc;
  1015. cmMemPtrFree(&p->ttmV);
  1016. cmMemPtrFree(&p->sfM);
  1017. cmMemPtrFree(&p->barkIdxV);
  1018. cmMemPtrFree(&p->barkCntV);
  1019. cmMemPtrFree(&p->outV);
  1020. cmObjFree(pp);
  1021. return rc;
  1022. }
  1023. cmRC_t cmSonesInit( cmSones* p, double srate, unsigned barkBandCnt, unsigned binCnt, unsigned flags )
  1024. {
  1025. p->ttmV = cmMemResize( cmReal_t, p->ttmV, binCnt);
  1026. p->sfM = cmMemResize( cmReal_t, p->sfM, binCnt*barkBandCnt);
  1027. p->barkIdxV = cmMemResize( unsigned, p->barkIdxV, barkBandCnt);
  1028. p->barkCntV = cmMemResize( unsigned, p->barkCntV, barkBandCnt);
  1029. p->outV = cmMemResize( cmReal_t, p->outV, barkBandCnt);
  1030. // calc outer ear filter
  1031. cmVOR_TerhardtThresholdMask( p->ttmV, binCnt, srate, kNoTtmFlags );
  1032. // calc shroeder spreading function
  1033. cmVOR_ShroederSpreadingFunc(p->sfM, barkBandCnt, srate);
  1034. // calc the bin to bark maps
  1035. p->barkBandCnt = cmVOR_BarkMap( p->barkIdxV, p->barkCntV, barkBandCnt, binCnt, srate );
  1036. //unsigned i = 0;
  1037. //for(; i<barkBandCnt; ++i)
  1038. // printf("%i %i %i\n", i+1, barkIdxV[i]+1, barkCntV[i]);
  1039. bool elFl = cmIsFlag(p->flags, kUseEqlLoudSonesFl);
  1040. p->binCnt = binCnt;
  1041. p->outN = elFl ? cmSonesEqlConCnt : p->barkBandCnt;
  1042. p->overallLoudness = 0;
  1043. p->flags = flags;
  1044. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"sones");
  1045. //p->sonesSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kSones_FId, p->outN );
  1046. //p->loudSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kLoud_FId, 1 );
  1047. return cmOkRC;
  1048. }
  1049. cmRC_t cmSonesFinal( cmSones* p )
  1050. {
  1051. //if( p != NULL )
  1052. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1053. return cmOkRC;
  1054. }
  1055. cmRC_t cmSonesExec( cmSones* p, const cmReal_t* magPowV, unsigned binCnt )
  1056. {
  1057. assert( binCnt == p->binCnt );
  1058. // Equal-loudness and phon map from: Y. Wonho, 1999, EMBSD: an objective speech quality measure based on audible distortion,
  1059. // equal-loudness contours
  1060. double eqlcon[cmSonesEqlConCnt][cmSonesEqlConBinCnt] =
  1061. {
  1062. {12,7,4,1,0,0,0,-0.5,-2,-3,-7,-8,-8.5,-8.5,-8.5},
  1063. {20,17,14,12,10,9.5,9,8.5,7.5,6.5,4,3,2.5,2,2.5},
  1064. {29,26,23,21,20,19.5,19.5,19,18,17,15,14,13.5,13,13.5},
  1065. {36,34,32,30,29,28.5,28.5,28.5,28,27.5,26,25,24.5,24,24.5},
  1066. {45,43,41,40,40,40,40,40,40,39.5,38,37,36.5,36,36.5},
  1067. {53,51,50,49,48.5,48.5,49,49,49,49,48,47,46.5,45.5,46},
  1068. {62,60,59,58,58,58.5,59,59,59,59,58,57.5,57,56,56},
  1069. {70,69,68,67.5,67.5,68,68,68,68,68,67,66,65.5,64.5,64.5},
  1070. {79,79,79,79,79,79,79,79,78,77.5,76,75,74.5,73,73},
  1071. {89,89,89,89.5,90,90,90,89.5,89,88.5,87,86,85.5,84,83.5},
  1072. {100,100,100,100,100,99.5,99,99,98.5,98,96,95,94.5,93.5,93},
  1073. {112,112,112,112,111,110.5,109.5,109,108.5,108,106,105,104.5,103,102.5},
  1074. {122,122,121,121,120.5,120,119,118,117,116.5,114.5,113.5,113,111, 110.5}
  1075. };
  1076. // loudness levels (phone scales)
  1077. double phons[cmSonesEqlConCnt]= {0.0,10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,110.0,120.0};
  1078. unsigned i,j;
  1079. cmReal_t t0[ binCnt ];
  1080. cmReal_t t1[ p->barkBandCnt ];
  1081. cmReal_t t2[ p->barkBandCnt ];
  1082. unsigned* idxV = p->barkIdxV;
  1083. unsigned* cntV = p->barkCntV;
  1084. cmReal_t* sfM = p->sfM;
  1085. // apply the outer ear filter
  1086. cmVOR_MultVVV( t0, binCnt, magPowV, p->ttmV);
  1087. // apply the bark frequency warping
  1088. for(i=0; i<p->barkBandCnt; ++i)
  1089. {
  1090. if( cntV[i] == 0 )
  1091. t1[i] = 0;
  1092. else
  1093. {
  1094. t1[i] = t0[ idxV[i] ];
  1095. for(j=1; j<cntV[i]; ++j)
  1096. t1[i] += t0[ idxV[i] + j ];
  1097. }
  1098. }
  1099. // apply the spreading filters
  1100. cmVOR_MultVMV( t2, p->barkBandCnt, sfM, p->barkBandCnt, t1 );
  1101. bool elFl = cmIsFlag(p->flags, kUseEqlLoudSonesFl);
  1102. unsigned bandCnt = elFl ? cmMin(p->barkBandCnt,cmSonesEqlConBinCnt) : p->barkBandCnt;
  1103. //p->outN = elFl ? cmSonesEqlConCnt : p->barkBandCnt;
  1104. p->overallLoudness = 0;
  1105. for( i = 0; i <bandCnt; i++ )
  1106. {
  1107. // if using the equal-loudness contours begin with the third bark band
  1108. // and end with the 18th bark band
  1109. unsigned k = elFl ? i+3 : i;
  1110. if( k < p->barkBandCnt )
  1111. {
  1112. double v = t2[k];
  1113. // convert to db
  1114. v = 10*log10( v<1 ? 1 : v );
  1115. if( elFl )
  1116. {
  1117. // db to phons
  1118. // see: Y. Wonho, 1999, EMBSD: an objective speech quality measure based on audible distortion,
  1119. j = 0;
  1120. // find the equal loudness curve for this frequency and db level
  1121. while( v >= eqlcon[j][i] )
  1122. ++j;
  1123. if( j == cmSonesEqlConCnt )
  1124. {
  1125. cmCtxRtAssertFailed( &p->obj, cmArgAssertRC, "Bark band %i is out of range during equal-loudness mapping.",j );
  1126. continue;
  1127. }
  1128. // convert db to phons
  1129. if( j == 0 )
  1130. v = phons[0];
  1131. else
  1132. {
  1133. double t1 = ( v - eqlcon[j-1][i] ) / ( eqlcon[j][i] - eqlcon[j-1][i] );
  1134. v = phons[j-1] + t1 * (phons[j] - phons[j-1]);
  1135. }
  1136. }
  1137. // convert to sones
  1138. // bladon and lindblom, 1981, JASA, modelling the judment of vowel quality differences
  1139. if( v >= 40 )
  1140. p->outV[i] = pow(2,(v-40)/10);
  1141. else
  1142. p->outV[i] = pow(v/40,2.642);
  1143. p->overallLoudness += p->outV[i];
  1144. }
  1145. }
  1146. if( p->mfp != NULL )
  1147. cmMtxFileRealExec( p->mfp, p->outV, p->outN );
  1148. return cmOkRC;
  1149. }
  1150. void cmSonesTest()
  1151. {
  1152. cmKbRecd kb;
  1153. double srate = 44100;
  1154. unsigned bandCnt = 23;
  1155. unsigned binCnt = 513;
  1156. cmSample_t tv[ binCnt ];
  1157. cmSample_t sm[ bandCnt * bandCnt ];
  1158. cmSample_t t[ bandCnt * bandCnt ];
  1159. unsigned binIdxV[ bandCnt ];
  1160. unsigned cntV[ bandCnt ];
  1161. unsigned i;
  1162. cmPlotSetup("Sones",1,1);
  1163. cmVOS_TerhardtThresholdMask(tv,binCnt,srate, kModifiedTtmFl );
  1164. cmVOS_ShroederSpreadingFunc(sm, bandCnt, srate);
  1165. cmVOS_Transpose( t, sm, bandCnt, bandCnt );
  1166. bandCnt = cmVOS_BarkMap(binIdxV,cntV, bandCnt, binCnt, srate );
  1167. for(i=0; i<bandCnt; ++i)
  1168. printf("%i %i %i\n", i, binIdxV[i], cntV[i] );
  1169. for(i=0; i<bandCnt; ++i )
  1170. {
  1171. cmPlotLineS( NULL, NULL, t+(i*bandCnt), NULL, bandCnt, NULL, kSolidPlotLineId );
  1172. }
  1173. //cmPlotLineS( NULL, NULL, tv, NULL, binCnt, NULL, kSolidPlotLineId );
  1174. cmPlotDraw();
  1175. cmKeyPress(&kb);
  1176. }
  1177. //------------------------------------------------------------------------------------------------------------
  1178. cmAudioOffsetScale* cmAudioOffsetScaleAlloc( cmCtx* c, cmAudioOffsetScale* ap, unsigned procSmpCnt, double srate, cmSample_t offset, double rmsWndSecs, double dBref, unsigned flags )
  1179. {
  1180. cmAudioOffsetScale* p = cmObjAlloc( cmAudioOffsetScale, c, ap );
  1181. if( procSmpCnt > 0 && srate > 0 )
  1182. if( cmAudioOffsetScaleInit( p, procSmpCnt, srate, offset, rmsWndSecs, dBref, flags ) != cmOkRC )
  1183. cmAudioOffsetScaleFree(&p);
  1184. return p;
  1185. }
  1186. cmRC_t cmAudioOffsetScaleFree( cmAudioOffsetScale** pp )
  1187. {
  1188. cmRC_t rc = cmOkRC;
  1189. cmAudioOffsetScale* p = *pp;
  1190. if( pp == NULL || *pp == NULL )
  1191. return cmOkRC;
  1192. if((rc = cmAudioOffsetScaleFinal(p)) != cmOkRC )
  1193. return rc;
  1194. cmMemPtrFree(&p->cBufPtr);
  1195. cmMemPtrFree(&p->cCntPtr);
  1196. cmMemPtrFree(&p->outV);
  1197. cmObjFree(pp);
  1198. return rc;
  1199. }
  1200. cmRC_t cmAudioOffsetScaleInit( cmAudioOffsetScale* p, unsigned procSmpCnt, double srate, cmSample_t offset, double rmsWndSecs, double dBref, unsigned flags )
  1201. {
  1202. assert( procSmpCnt > 0 && srate > 0);
  1203. cmRC_t rc;
  1204. if((rc = cmAudioOffsetScaleFinal(p)) != cmOkRC )
  1205. return rc;
  1206. p->cBufCnt = 0;
  1207. if( cmIsFlag(flags, kRmsAudioScaleFl) )
  1208. {
  1209. if( rmsWndSecs > 0 )
  1210. {
  1211. unsigned rmsSmpCnt = srate * rmsWndSecs;
  1212. p->cBufCnt = (unsigned)ceil( rmsSmpCnt / procSmpCnt );
  1213. if( p->cBufCnt > 0 )
  1214. {
  1215. p->cBufPtr = cmMemResizeZ( cmReal_t, p->cBufPtr, p->cBufCnt );
  1216. p->cCntPtr = cmMemResizeZ( unsigned, p->cCntPtr, p->cBufCnt );
  1217. }
  1218. }
  1219. else
  1220. {
  1221. p->cBufCnt = 0;
  1222. p->cBufPtr = NULL;
  1223. p->cCntPtr = NULL;
  1224. }
  1225. }
  1226. p->cBufIdx = 0;
  1227. p->cBufCurCnt = 0;
  1228. p->cBufSum = 0;
  1229. p->cCntSum = 0;
  1230. p->outV = cmMemResize( cmSample_t, p->outV, procSmpCnt );
  1231. p->outN = procSmpCnt;
  1232. p->offset = offset;
  1233. p->dBref = dBref;
  1234. p->flags = flags;
  1235. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"audioOffsetScale");
  1236. return cmOkRC;
  1237. }
  1238. cmRC_t cmAudioOffsetScaleFinal( cmAudioOffsetScale* p )
  1239. {
  1240. //if( p != NULL)
  1241. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1242. return cmOkRC;
  1243. }
  1244. cmRC_t cmAudioOffsetScaleExec( cmAudioOffsetScale* p, const cmSample_t* sp, unsigned sn )
  1245. {
  1246. double Pref = 20.0 / 1000000; // 20 micro Pascals
  1247. cmSample_t* dbp = p->outV;
  1248. const cmSample_t* dep = dbp + sn;
  1249. double scale = 0;
  1250. // if no scaling was requested then add offset only
  1251. if( cmIsFlag(p->flags, kNoAudioScaleFl) )
  1252. {
  1253. while( dbp < dep )
  1254. *dbp++ = *sp++ + p->offset;
  1255. goto doneLabel;
  1256. }
  1257. // if fixed scaling
  1258. if( cmIsFlag(p->flags, kFixedAudioScaleFl) )
  1259. {
  1260. if( scale == 0 )
  1261. scale = pow(10,p->dBref/20);
  1262. while( dbp < dep )
  1263. *dbp++ = (*sp++ + p->offset) * scale;
  1264. }
  1265. else // if RMS scaling
  1266. {
  1267. double sum = 0;
  1268. double rms = 0;
  1269. while( dbp < dep )
  1270. {
  1271. double v = (*sp++ + p->offset) / Pref;
  1272. sum += v*v;
  1273. *dbp++ = v;
  1274. }
  1275. // if there is no RMS buffer calc RMS on procSmpCnt samles
  1276. if( p->cBufCnt == 0 )
  1277. rms = sqrt( sum / sn );
  1278. else
  1279. {
  1280. p->cBufSum -= p->cBufPtr[ p->cBufIdx ];
  1281. p->cBufSum += sum;
  1282. p->cCntSum -= p->cCntPtr[ p->cBufIdx ];
  1283. p->cCntSum += sn;
  1284. p->cBufIdx = (p->cBufIdx+1) % p->cBufCnt;
  1285. p->cBufCurCnt = cmMin( p->cBufCurCnt+1, p->cBufCnt );
  1286. assert( p->cCntSum > 0 );
  1287. rms = sqrt( p->cBufSum / p->cCntSum );
  1288. }
  1289. double sigSPL = 20*log10(rms);
  1290. scale = pow(10,(p->dBref - sigSPL)/20);
  1291. dbp = p->outV;
  1292. while( dbp < dep )
  1293. *dbp++ *= scale;
  1294. }
  1295. doneLabel:
  1296. dbp = p->outV + sn;
  1297. dep = p->outV + p->outN;
  1298. while( dbp < dep )
  1299. *dbp++ = 0;
  1300. if( p->mfp != NULL )
  1301. cmMtxFileSmpExec(p->mfp,p->outV,p->outN);
  1302. return cmOkRC;
  1303. }
  1304. //------------------------------------------------------------------------------------------------------------
  1305. cmSpecMeas* cmSpecMeasAlloc( cmCtx* c, cmSpecMeas* ap, double srate, unsigned binCnt, unsigned wndFrmCnt, unsigned flags )
  1306. {
  1307. cmSpecMeas* p = cmObjAlloc( cmSpecMeas, c, ap );
  1308. if( srate > 0 && binCnt > 0 )
  1309. if( cmSpecMeasInit( p, srate, binCnt, wndFrmCnt, flags ) != cmOkRC )
  1310. cmSpecMeasFree(&p);
  1311. return p;
  1312. }
  1313. cmRC_t cmSpecMeasFree( cmSpecMeas** pp )
  1314. {
  1315. cmRC_t rc = cmOkRC;
  1316. cmSpecMeas* p = *pp;
  1317. if( pp == NULL || *pp == NULL )
  1318. return cmOkRC;
  1319. if((rc = cmSpecMeasFinal(p)) != cmOkRC )
  1320. return rc;
  1321. cmMemPtrFree(&p->rmsV);
  1322. cmMemPtrFree(&p->hfcV);
  1323. cmMemPtrFree(&p->scnV);
  1324. cmObjFree(pp);
  1325. return rc;
  1326. }
  1327. cmRC_t cmSpecMeasInit( cmSpecMeas* p, double srate, unsigned binCnt, unsigned wndFrmCnt, unsigned flags )
  1328. {
  1329. cmRC_t rc;
  1330. if((rc = cmSpecMeasFinal(p)) != cmOkRC )
  1331. return rc;
  1332. if( cmIsFlag(flags, kUseWndSpecMeasFl) )
  1333. {
  1334. p->rmsV = cmMemResizeZ( cmReal_t, p->rmsV, wndFrmCnt );
  1335. p->hfcV = cmMemResizeZ( cmReal_t, p->hfcV, wndFrmCnt );
  1336. p->scnV = cmMemResizeZ( cmReal_t, p->scnV, wndFrmCnt );
  1337. }
  1338. p->rmsSum = 0;
  1339. p->hfcSum = 0;
  1340. p->scnSum = 0;
  1341. p->binCnt = binCnt;
  1342. p->flags = flags;
  1343. p->wndFrmCnt = wndFrmCnt;
  1344. p->frameCnt = 0;
  1345. p->frameIdx = 0;
  1346. p->binHz = srate / ((binCnt-1) * 2);
  1347. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"specMeas");
  1348. //p->rmsSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kRMS_FId, 1);
  1349. //p->hfcSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kHFC_FId, 1);
  1350. //p->scSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kSC_FId, 1);
  1351. //p->ssSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kSS_FId, 1);
  1352. return cmOkRC;
  1353. }
  1354. cmRC_t cmSpecMeasFinal( cmSpecMeas* p )
  1355. {
  1356. //if( p != NULL )
  1357. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1358. return cmOkRC;
  1359. }
  1360. cmRC_t cmSpecMeasExec( cmSpecMeas* p, const cmReal_t* magPowV, unsigned binCnt )
  1361. {
  1362. assert( binCnt == p->binCnt );
  1363. unsigned i = 0;
  1364. const cmReal_t* sbp = magPowV;
  1365. const cmReal_t* sep = sbp + binCnt;
  1366. cmReal_t rmsSum = 0;
  1367. cmReal_t hfcSum = 0;
  1368. cmReal_t scnSum = 0;
  1369. cmReal_t ssSum = 0;
  1370. for(i=0; sbp < sep; ++i, ++sbp )
  1371. {
  1372. rmsSum += *sbp;
  1373. hfcSum += *sbp * i;
  1374. scnSum += *sbp * i * p->binHz;
  1375. }
  1376. p->frameCnt++;
  1377. if( cmIsFlag(p->flags, kUseWndSpecMeasFl) )
  1378. {
  1379. p->frameCnt = cmMin( p->frameCnt, p->wndFrmCnt );
  1380. cmReal_t* rmsV = p->rmsV + p->frameIdx;
  1381. cmReal_t* hfcV = p->hfcV + p->frameIdx;
  1382. cmReal_t* scnV = p->scnV + p->frameIdx;
  1383. p->rmsSum -= *rmsV;
  1384. p->hfcSum -= *hfcV;
  1385. p->scnSum -= *scnV;
  1386. *rmsV = rmsSum;
  1387. *hfcV = hfcSum;
  1388. *scnV = scnSum;
  1389. p->frameIdx = (p->frameIdx+1) % p->frameCnt;
  1390. }
  1391. p->rmsSum += rmsSum;
  1392. p->hfcSum += hfcSum;
  1393. p->scnSum += scnSum;
  1394. p->rms = sqrt(p->rmsSum / (p->binCnt * p->frameCnt) );
  1395. p->hfc = p->hfcSum / ( p->binCnt * p->frameCnt );
  1396. p->sc = p->scnSum / cmMax( cmReal_EPSILON, p->rmsSum );
  1397. sbp = magPowV;
  1398. for(i=0; sbp < sep; ++i )
  1399. {
  1400. cmReal_t t = (i*p->binHz) - p->sc;
  1401. ssSum += *sbp++ * (t*t);
  1402. }
  1403. p->ss = sqrt(ssSum / cmMax( cmReal_EPSILON, p->rmsSum ));
  1404. if( p->mfp != NULL )
  1405. {
  1406. cmReal_t a[4] = { p->rms, p->hfc, p->sc, p->ss };
  1407. cmMtxFileRealExec( p->mfp, a, 4 );
  1408. }
  1409. return cmOkRC;
  1410. }
  1411. //------------------------------------------------------------------------------------------------------------
  1412. cmSigMeas* cmSigMeasAlloc( cmCtx* c, cmSigMeas* ap, double srate, unsigned procSmpCnt, unsigned measSmpCnt )
  1413. {
  1414. cmSigMeas* p = cmObjAlloc( cmSigMeas, c, ap );
  1415. p->sbp = cmShiftBufAlloc(c,&p->shiftBuf,0,0,0);
  1416. if( srate > 0 && procSmpCnt > 0 && measSmpCnt > 0 )
  1417. if( cmSigMeasInit( p, srate, procSmpCnt, measSmpCnt ) != cmOkRC )
  1418. cmSigMeasFree(&p);
  1419. return p;
  1420. }
  1421. cmRC_t cmSigMeasFree( cmSigMeas** pp )
  1422. {
  1423. cmRC_t rc = cmOkRC;
  1424. cmSigMeas* p = *pp;
  1425. if( pp==NULL || *pp==NULL)
  1426. return cmOkRC;
  1427. if((rc = cmSigMeasFinal(p)) != cmOkRC )
  1428. return rc;
  1429. cmShiftBufFree(&p->sbp);
  1430. cmObjFree(pp);
  1431. return rc;
  1432. }
  1433. cmRC_t cmSigMeasInit( cmSigMeas* p, double srate, unsigned procSmpCnt, unsigned measSmpCnt )
  1434. {
  1435. cmRC_t rc;
  1436. if((rc = cmSigMeasFinal(p)) != cmOkRC )
  1437. return rc;
  1438. if( procSmpCnt != measSmpCnt )
  1439. cmShiftBufInit( p->sbp, procSmpCnt, measSmpCnt, procSmpCnt );
  1440. p->zcrDelay = 0;
  1441. p->srate = srate;
  1442. p->measSmpCnt = measSmpCnt;
  1443. p->procSmpCnt = procSmpCnt;
  1444. //p->zcrSpRegId = cmStatsProcReg( p->obj.ctx->statsProcPtr, kZCR_FId, 1 );
  1445. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"sigMeas");
  1446. return cmOkRC;
  1447. }
  1448. cmRC_t cmSigMeasFinal( cmSigMeas* p )
  1449. {
  1450. //if( p != NULL )
  1451. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1452. return cmOkRC;
  1453. }
  1454. cmRC_t cmSigMeasExec( cmSigMeas* p, const cmSample_t* sp, unsigned sn )
  1455. {
  1456. if( p->procSmpCnt != p->measSmpCnt )
  1457. {
  1458. cmShiftBufExec( p->sbp, sp, sn );
  1459. sp = p->sbp->outV;
  1460. sn = p->sbp->wndSmpCnt;
  1461. assert( p->sbp->wndSmpCnt == p->measSmpCnt );
  1462. }
  1463. unsigned zcn = cmVOS_ZeroCrossCount( sp, sn, NULL );
  1464. p->zcr = (cmReal_t)zcn * p->srate / p->measSmpCnt;
  1465. if( p->mfp != NULL )
  1466. cmMtxFileRealExec( p->mfp, &p->zcr, 1 );
  1467. return cmOkRC;
  1468. }
  1469. //------------------------------------------------------------------------------------------------------------
  1470. cmSRC* cmSRCAlloc( cmCtx* c, cmSRC* ap, double srate, unsigned procSmpCnt, unsigned upFact, unsigned dnFact )
  1471. {
  1472. cmSRC* p = cmObjAlloc( cmSRC, c,ap );
  1473. cmFilterAlloc(c,&p->filt,NULL,0,NULL,0,0,NULL);
  1474. if( srate > 0 && procSmpCnt > 0 )
  1475. if( cmSRCInit( p, srate, procSmpCnt, upFact, dnFact ) != cmOkRC )
  1476. cmSRCFree(&p);
  1477. return p;
  1478. }
  1479. cmRC_t cmSRCFree( cmSRC** pp )
  1480. {
  1481. cmRC_t rc;
  1482. if( pp != NULL && *pp != NULL )
  1483. {
  1484. cmSRC* p = *pp;
  1485. if((rc = cmSRCFinal( p )) == cmOkRC )
  1486. {
  1487. cmFilter* fp = &p->filt;
  1488. cmFilterFree(&fp);
  1489. cmMemPtrFree(&p->outV);
  1490. cmObjFree(pp);
  1491. }
  1492. }
  1493. return cmOkRC;
  1494. }
  1495. cmRC_t cmSRCInit( cmSRC* p, double srate, unsigned procSmpCnt, unsigned upFact, unsigned dnFact )
  1496. {
  1497. cmRC_t rc;
  1498. if((rc = cmSRCFinal(p)) != cmOkRC )
  1499. return rc;
  1500. double hiRate = upFact * srate;
  1501. double loRate = hiRate / dnFact;
  1502. double minRate= cmMin( loRate, srate );
  1503. double fcHz = minRate/2;
  1504. double dHz = (fcHz * .1); // transition band is 5% of min sample rate
  1505. double passHz = fcHz-dHz;
  1506. double stopHz = fcHz;
  1507. double passDb = 0.001;
  1508. double stopDb = 20;
  1509. cmFilterInitEllip( &p->filt, hiRate, passHz, stopHz, passDb, stopDb, procSmpCnt, NULL );
  1510. //printf("CoeffCnt:%i dHz:%f passHz:%f stopHz:%f passDb:%f stopDb:%f\n", p->fir.coeffCnt, dHz, passHz, stopHz, passDb, stopDb );
  1511. p->outN = (unsigned)ceil(procSmpCnt * upFact / dnFact);
  1512. p->outV = cmMemResize( cmSample_t, p->outV, p->outN );
  1513. p->upi = 0;
  1514. p->dni = 0;
  1515. p->upFact = upFact;
  1516. p->dnFact = dnFact;
  1517. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"src");
  1518. return cmOkRC;
  1519. }
  1520. cmRC_t cmSRCFinal( cmSRC* p )
  1521. {
  1522. //if( p != NULL )
  1523. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1524. return cmOkRC;
  1525. }
  1526. cmRC_t cmSRCExec( cmSRC* p, const cmSample_t* sp, unsigned sn )
  1527. {
  1528. const cmSample_t* sep = sp + sn;
  1529. cmSample_t* op = p->outV;
  1530. const cmSample_t* oep = op + p->outN;
  1531. unsigned iN = sn * p->upFact;
  1532. unsigned i,j;
  1533. // run the filter at the upsampled rate ...
  1534. for(i=0; i<iN; ++i)
  1535. {
  1536. assert( p->upi!=0 || sp<sep );
  1537. cmSample_t x0 = p->upi==0 ? *sp++ : 0,
  1538. y0 = x0 * p->filt.b0 + p->filt.d[0];
  1539. // ... but output at the down sampled rate
  1540. if( p->dni==0 )
  1541. {
  1542. assert( op < oep );
  1543. *op++ = y0;
  1544. }
  1545. // advance the filter delay line
  1546. for(j=0; j<p->filt.cn; ++j)
  1547. p->filt.d[j] = p->filt.b[j]*x0 - p->filt.a[j]*y0 + p->filt.d[j+1];
  1548. // update the input/output clocks
  1549. p->upi = (p->upi + 1) % p->upFact;
  1550. p->dni = (p->dni + 1) % p->dnFact;
  1551. }
  1552. p->outN = op - p->outV;
  1553. if( p->mfp != NULL )
  1554. cmMtxFileSmpExec(p->mfp,p->outV,p->outN );
  1555. return cmOkRC;
  1556. }
  1557. //------------------------------------------------------------------------------------------------------------
  1558. cmConstQ* cmConstQAlloc( cmCtx* c, cmConstQ* ap, double srate, unsigned minMidiPitch, unsigned maxMidiPitch, unsigned binsPerOctave, double thresh )
  1559. {
  1560. cmConstQ* p = cmObjAlloc( cmConstQ, c, ap );
  1561. if( srate >0 )
  1562. if( cmConstQInit(p,srate,minMidiPitch,maxMidiPitch,binsPerOctave,thresh) != cmOkRC )
  1563. cmConstQFree(&p);
  1564. return p;
  1565. }
  1566. cmRC_t cmConstQFree( cmConstQ** pp )
  1567. {
  1568. cmRC_t rc;
  1569. cmConstQ* p = *pp;
  1570. if( pp==NULL || *pp==NULL)
  1571. return cmOkRC;
  1572. if((rc = cmConstQFinal(p)) != cmOkRC )
  1573. return rc;
  1574. cmMemPtrFree(&p->fiV);
  1575. cmMemPtrFree(&p->foV);
  1576. cmMemPtrFree(&p->skM);
  1577. cmMemPtrFree(&p->outV);
  1578. cmMemPtrFree(&p->magV);
  1579. cmMemPtrFree(&p->skBegV);
  1580. cmMemPtrFree(&p->skEndV);
  1581. cmObjFree(pp);
  1582. return cmOkRC;
  1583. }
  1584. cmRC_t cmConstQInit( cmConstQ* p, double srate, unsigned minMidiPitch, unsigned maxMidiPitch, unsigned binsPerOctave, double thresh )
  1585. {
  1586. cmRC_t rc;
  1587. if((rc = cmConstQFinal(p)) != cmOkRC )
  1588. return rc;
  1589. cmReal_t minHz = cmMidiToHz(minMidiPitch);
  1590. cmReal_t maxHz = cmMidiToHz(maxMidiPitch);
  1591. cmReal_t Q = 1.0/(pow(2,(double)1.0/binsPerOctave)-1);
  1592. unsigned K = (unsigned)ceil( binsPerOctave * log2(maxHz/minHz) );
  1593. unsigned fftN = cmNextPowerOfTwo( (unsigned)ceil(Q*srate/minHz) );
  1594. unsigned k = 0;
  1595. p->fiV = cmMemResize(cmComplexR_t, p->fiV, fftN);
  1596. p->foV = cmMemResize(cmComplexR_t, p->foV, fftN);
  1597. cmFftPlanR_t plan = cmFft1dPlanAllocR(fftN, p->fiV, p->foV, FFTW_FORWARD, FFTW_ESTIMATE );
  1598. p->wndSmpCnt = fftN;
  1599. p->constQBinCnt = K;
  1600. p->binsPerOctave= binsPerOctave;
  1601. p->skM = cmMemResizeZ( cmComplexR_t, p->skM, p->wndSmpCnt * p->constQBinCnt);
  1602. p->outV = cmMemResizeZ( cmComplexR_t, p->outV, p->constQBinCnt);
  1603. p->magV = cmMemResizeZ( cmReal_t, p->magV, p->constQBinCnt);
  1604. p->skBegV = cmMemResizeZ( unsigned, p->skBegV, p->constQBinCnt);
  1605. p->skEndV = cmMemResizeZ( unsigned, p->skEndV, p->constQBinCnt);
  1606. //p->mfp = cmCtxAllocDebugFile( p->obj.ctx, "constQ");
  1607. //printf("hz:%f %f bpo:%i sr:%f thresh:%f Q:%f K%i (cols) fftN:%i (rows)\n", minHz,maxHz,binsPerOctave,srate,thresh,Q,K,fftN);
  1608. double* hamm = NULL;
  1609. // note that the bands are created in reverse order
  1610. for(k=0; k<K; ++k)
  1611. {
  1612. unsigned iN = ceil( Q * srate / (minHz * pow(2,(double)k/binsPerOctave)));
  1613. unsigned start = fftN/2;
  1614. //double hamm[ iN ];
  1615. hamm = cmMemResizeZ(double,hamm,iN);
  1616. memset( p->fiV, 0, fftN * sizeof(cmComplexR_t));
  1617. memset( p->foV, 0, fftN * sizeof(cmComplexR_t));
  1618. cmVOD_Hamming( hamm, iN );
  1619. cmVOD_DivVS( hamm, iN, iN );
  1620. if( cmIsEvenU(iN) )
  1621. start -= iN/2;
  1622. else
  1623. start -= (iN+1)/2;
  1624. //printf("k:%i iN:%i start:%i %i\n",k,iN,start,start+iN-1);
  1625. unsigned i = start;
  1626. for(; i<=start+iN-1; ++i)
  1627. {
  1628. double arg = 2.0*M_PI*Q*(i-start)/iN;
  1629. double mag = hamm[i-start];
  1630. p->fiV[i-1] = (mag * cos(arg)) + (mag * I * sin(arg));
  1631. }
  1632. cmFftExecuteR(plan);
  1633. // since the bands are created in reverse order they are also stored in reverse order
  1634. // (i.e column k-1 is stored first and column 0 is stored last)
  1635. i=0;
  1636. unsigned minIdx = -1;
  1637. unsigned maxIdx = 0;
  1638. for(; i<fftN; ++i)
  1639. {
  1640. bool fl = cabs(p->foV[i]) <= thresh;
  1641. p->skM[ (k*p->wndSmpCnt) + i ] = fl ? 0 : p->foV[i]/fftN;
  1642. if( fl==false && minIdx == -1 )
  1643. minIdx = i;
  1644. if( fl==false && i>maxIdx )
  1645. maxIdx = i;
  1646. }
  1647. p->skBegV[k] = minIdx;
  1648. p->skEndV[k] = maxIdx;
  1649. }
  1650. cmMemPtrFree(&hamm);
  1651. cmFftPlanFreeR(plan);
  1652. return cmOkRC;
  1653. }
  1654. cmRC_t cmConstQFinal( cmConstQ* p )
  1655. {
  1656. //if( p != NULL )
  1657. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1658. return cmOkRC;
  1659. }
  1660. cmRC_t cmConstQExec( cmConstQ* p, const cmComplexR_t* ftV, unsigned srcBinCnt )
  1661. {
  1662. //acVORC_MultVVM( p->outV, p->constQBinCnt,ftV,p->wndSmpCnt, p->skM );
  1663. cmReal_t* mbp = p->magV;
  1664. cmComplexR_t* dbp = p->outV;
  1665. const cmComplexR_t* dep = p->outV + p->constQBinCnt;
  1666. unsigned i = 0;
  1667. for(; dbp < dep; ++dbp,++i,++mbp )
  1668. {
  1669. const cmComplexR_t* sbp = ftV + p->skBegV[i];
  1670. const cmComplexR_t* kp = p->skM + (i*p->wndSmpCnt) + p->skBegV[i];
  1671. const cmComplexR_t* ep = kp + (p->skEndV[i] - p->skBegV[i]) + 1;
  1672. *dbp = 0;
  1673. while( kp < ep )
  1674. *dbp += *sbp++ * *kp++;
  1675. *mbp = cmCabsR(*dbp);
  1676. }
  1677. if( p->mfp != NULL )
  1678. cmMtxFileComplexExec( p->mfp, p->outV, p->constQBinCnt, 1 );
  1679. return cmOkRC;
  1680. }
  1681. void cmConstQTest( cmConstQ* p )
  1682. {
  1683. cmKbRecd kb;
  1684. unsigned i,j;
  1685. cmSample_t* t = cmMemAlloc( cmSample_t, p->wndSmpCnt );
  1686. for(i=0; i<p->constQBinCnt; ++i)
  1687. {
  1688. for(j=0; j<p->wndSmpCnt; ++j)
  1689. t[j] = cabs( p->skM[ (i*p->wndSmpCnt) + j ]);
  1690. //cmPlotClear();
  1691. cmPlotLineS( NULL, NULL, t, NULL, 500, NULL, kSolidPlotLineId );
  1692. }
  1693. cmPlotDraw();
  1694. cmKeyPress(&kb);
  1695. cmMemPtrFree(&t);
  1696. }
  1697. //------------------------------------------------------------------------------------------------------------
  1698. cmHpcp* cmTunedHpcpAlloc( cmCtx* c, cmHpcp* ap, unsigned binsPerOctave, unsigned constQBinCnt, unsigned cqMinMidiPitch, unsigned frameCnt, unsigned medFiltOrder )
  1699. {
  1700. cmHpcp* p = cmObjAlloc( cmHpcp, c, ap );
  1701. if( binsPerOctave > 0 && constQBinCnt >> 0 )
  1702. if( cmTunedHpcpInit( p, binsPerOctave, constQBinCnt, cqMinMidiPitch, frameCnt, medFiltOrder ) != cmOkRC)
  1703. cmTunedHpcpFree(&p);
  1704. return p;
  1705. }
  1706. cmRC_t cmTunedHpcpFree( cmHpcp** pp )
  1707. {
  1708. cmRC_t rc = cmOkRC;
  1709. cmHpcp* p = *pp;
  1710. if(pp==NULL || *pp==NULL)
  1711. return cmOkRC;
  1712. if((rc = cmTunedHpcpFinal(p)) != cmOkRC )
  1713. return rc;
  1714. cmMemPtrFree(&p->hpcpM);
  1715. cmMemPtrFree(&p->fhpcpM);
  1716. cmMemPtrFree(&p->histV);
  1717. cmMemPtrFree(&p->outM);
  1718. cmMemPtrFree(&p->meanV);
  1719. cmMemPtrFree(&p->varV);
  1720. cmObjFree(pp);
  1721. return cmOkRC;
  1722. }
  1723. cmRC_t cmTunedHpcpInit( cmHpcp* p, unsigned binsPerOctave, unsigned constQBinCnt, unsigned cqMinMidiPitch, unsigned frameCnt, unsigned medFiltOrder )
  1724. {
  1725. assert( binsPerOctave % kStPerOctave == 0 );
  1726. assert( cmIsOddU( binsPerOctave / kStPerOctave ) );
  1727. cmRC_t rc;
  1728. if((rc = cmTunedHpcpFinal(p)) != cmOkRC )
  1729. return rc;
  1730. p->histN = binsPerOctave/kStPerOctave;
  1731. p->hpcpM = cmMemResizeZ( cmReal_t, p->hpcpM, frameCnt*binsPerOctave );
  1732. p->fhpcpM = cmMemResizeZ( cmReal_t, p->fhpcpM, binsPerOctave*frameCnt );
  1733. p->histV = cmMemResizeZ( unsigned, p->histV, p->histN );
  1734. p->outM = cmMemResizeZ( cmReal_t, p->outM, kStPerOctave * frameCnt );
  1735. p->meanV = cmMemResizeZ( cmReal_t, p->meanV, kStPerOctave );
  1736. p->varV = cmMemResizeZ( cmReal_t, p->varV, kStPerOctave );
  1737. p->constQBinCnt = constQBinCnt;
  1738. p->binsPerOctave = binsPerOctave;
  1739. p->frameCnt = frameCnt;
  1740. p->frameIdx = 0;
  1741. p->cqMinMidiPitch= cqMinMidiPitch;
  1742. p->medFiltOrder = medFiltOrder;
  1743. //p->mf0p = cmCtxAllocDebugFile(p->obj.ctx,"hpcp");
  1744. //p->mf1p = cmCtxAllocDebugFile(p->obj.ctx,"fhpcp");
  1745. //p->mf2p = cmCtxAllocDebugFile(p->obj.ctx,"chroma");
  1746. return cmOkRC;
  1747. }
  1748. cmRC_t cmTunedHpcpFinal( cmHpcp* p )
  1749. {
  1750. /*
  1751. if( p != NULL )
  1752. {
  1753. cmCtxFreeDebugFile(p->obj.ctx,&p->mf0p);
  1754. cmCtxFreeDebugFile(p->obj.ctx,&p->mf1p);
  1755. cmCtxFreeDebugFile(p->obj.ctx,&p->mf2p);
  1756. }
  1757. */
  1758. return cmOkRC;
  1759. }
  1760. cmRC_t cmTunedHpcpExec( cmHpcp* p, const cmComplexR_t* cqp, unsigned cqn )
  1761. {
  1762. assert( cqn == p->constQBinCnt );
  1763. // if there is no space to store the output then do nothing
  1764. if( p->frameIdx >= p->frameCnt )
  1765. return cmOkRC;
  1766. unsigned octCnt = (unsigned)floor(p->constQBinCnt / p->binsPerOctave);
  1767. unsigned i;
  1768. cmReal_t hpcpV[ p->binsPerOctave + 2 ];
  1769. unsigned idxV[ p->binsPerOctave ];
  1770. unsigned binsPerSt = p->binsPerOctave / kStPerOctave;
  1771. // Notice that the first and last elements of p->hpcp are reserved for
  1772. // use in producing the appeareance of circularity for the peak picking
  1773. // algorithm. The cmtual hpcp[] data begins on the index 1 (not 0) and
  1774. // ends on p->binsPerOctave (not p->binsPerOctave-1).
  1775. // sum the constQBinCnt constant Q bins into binsPerOctave bins to form the HPCP
  1776. for(i=0; i<p->binsPerOctave; ++i)
  1777. {
  1778. cmReal_t sum = 0;
  1779. const cmComplexR_t* sbp = cqp + i;
  1780. const cmComplexR_t* sep = cqp + (octCnt * p->binsPerOctave);
  1781. for(; sbp < sep; sbp += p->binsPerOctave)
  1782. sum += cmCabsR(*sbp);
  1783. hpcpV[i+1] = sum;
  1784. }
  1785. // shift the lowest ST center bin to (binsPerSt+1)/2 such that an equal number of
  1786. // flat and sharp bins are above an below it
  1787. int rotateCnt = ((binsPerSt+1)/2) - 1;
  1788. // shift pitch class C to the lowest semitone boundary
  1789. rotateCnt -= ( 48-(int)p->cqMinMidiPitch) * binsPerSt;
  1790. // perform the shift
  1791. cmVOR_Rotate(hpcpV+1, p->binsPerOctave, rotateCnt);
  1792. // duplicate the first and last bin to produce circularity in the hpcp
  1793. hpcpV[0] = hpcpV[ p->binsPerOctave ];
  1794. hpcpV[ p->binsPerOctave+1 ] = hpcpV[1];
  1795. // locate the indexes of the positive peaks in the hpcp
  1796. unsigned pkN = cmVOR_PeakIndexes( idxV, p->binsPerOctave, hpcpV, p->binsPerOctave, 0 );
  1797. // Convert the peak indexes to values in the range 0 to binsPerSet-1
  1798. // If stPerBin == 3 : 0=flat 1=in tune 2=sharp
  1799. cmVOU_Mod( idxV, pkN, binsPerSt );
  1800. // Form a histogram to keep count of the number of flat,in-tune and sharp peaks
  1801. cmVOU_Hist( p->histV, binsPerSt, idxV, pkN );
  1802. // store the hpcpV[] to the row p->hpcpM[p->frameIdx,:]
  1803. cmVOR_CopyN( p->hpcpM + p->frameIdx, p->binsPerOctave, p->frameCnt, hpcpV+1, 1 );
  1804. // write the hpcp debug file
  1805. if( p->mf0p != NULL )
  1806. cmMtxFileRealExecN( p->mf0p, p->hpcpM + p->frameIdx, p->binsPerOctave, p->frameCnt );
  1807. p->frameIdx++;
  1808. return cmOkRC;
  1809. }
  1810. cmRC_t cmTunedHpcpTuneAndFilter( cmHpcp* p)
  1811. {
  1812. // note: p->frameIdx now holds the cmtual count of frames in p->hpcpA[].
  1813. // p->frameCnt holds the allocated count of frames in p->hpcpA[].
  1814. unsigned i,j;
  1815. // filter each column of hpcpA[] into each row of fhpcpA[]
  1816. for(i=0; i<p->binsPerOctave; ++i)
  1817. {
  1818. cmVOR_MedianFilt( p->hpcpM + (i * p->frameCnt), p->frameIdx, p->medFiltOrder, p->fhpcpM + i, p->binsPerOctave );
  1819. // write the fhpcp[i,:] to the debug file
  1820. if( p->mf1p != NULL )
  1821. cmMtxFileRealExecN( p->mf1p, p->fhpcpM + i, p->frameIdx, p->binsPerOctave );
  1822. }
  1823. unsigned binsPerSt = p->histN;
  1824. assert( (binsPerSt > 0) && (cmIsOddU(binsPerSt)) );
  1825. unsigned maxIdx = cmVOU_MaxIndex(p->histV,binsPerSt,1);
  1826. int tuneShift = -(maxIdx - ((binsPerSt+1)/2));
  1827. cmReal_t gaussWndV[ binsPerSt ];
  1828. // generate a gaussian window
  1829. cmVOR_GaussWin( gaussWndV, binsPerSt, 2.5 );
  1830. // Rotate the window to apply tuning via the weighted sum operation below
  1831. // (the result will be equivalent to rotating p->fhpcpM[] prior to reducing the )
  1832. cmVOR_Rotate(gaussWndV, binsPerSt, tuneShift);
  1833. // zero the meanV[] before summing into it
  1834. cmVOR_Fill(p->meanV,kStPerOctave,0);
  1835. // for each frame
  1836. for(i=0; i<p->frameIdx; ++i)
  1837. {
  1838. // for each semitone
  1839. for(j=0; j<kStPerOctave; ++j)
  1840. {
  1841. // reduce each semitone to a single value by forming a weighted sum of all the assoc'd bins
  1842. cmReal_t sum = cmVOR_MultSumVV( gaussWndV, p->fhpcpM + (i*p->binsPerOctave) + (j*binsPerSt), binsPerSt );
  1843. // store time-series output to the ith column
  1844. p->outM[ (i*kStPerOctave) + j ] = sum;
  1845. // calc the sum of all chroma values in bin j.
  1846. p->meanV[ j ] += sum;
  1847. }
  1848. // write the chroma debug file
  1849. if( p->mf2p != NULL )
  1850. cmMtxFileRealExec( p->mf2p, p->outM + (i*kStPerOctave), kStPerOctave );
  1851. }
  1852. // form the chroma mean from the sum calc'd above
  1853. cmVOR_DivVS( p->meanV, kStPerOctave, p->frameIdx );
  1854. // variance
  1855. for(j=0; j<kStPerOctave; ++j)
  1856. p->varV[j] = cmVOR_VarianceN( p->outM + j, p->frameIdx, kStPerOctave, p->meanV + j );
  1857. return cmOkRC;
  1858. }
  1859. //------------------------------------------------------------------------------------------------------------
  1860. /*
  1861. cmStatsProc* cmStatsProcAlloc( cmCtx* c, cmStatsProc* p, unsigned wndEleCnt, unsigned flags )
  1862. {
  1863. cmStatsProc* op = cmObjAlloc(cmStatsProc,c,p);
  1864. if( wndEleCnt > 0 )
  1865. if( cmStatsProcInit(op, wndEleCnt, flags ) != cmOkRC )
  1866. cmStatsProcFree(&op);
  1867. if( op != NULL )
  1868. cmCtxSetStatsProc(c,op);
  1869. return op;
  1870. }
  1871. cmRC_t cmStatsProcFree( cmStatsProc** pp )
  1872. {
  1873. cmRC_t rc = cmOkRC;
  1874. cmStatsProc* p = *pp;
  1875. if( pp == NULL || *pp == NULL )
  1876. return cmOkRC;
  1877. if((rc = cmStatsProcFinal(p) ) != cmOkRC )
  1878. return rc;
  1879. cmCtxSetStatsProc(p->obj.ctx,NULL); // complement to cmSetStatsProc() in cmStatsProcAlloc()
  1880. cmMemPtrFree(&p->regArrayV);
  1881. cmMemPtrFree(&p->m);
  1882. cmMemPtrFree(&p->sumV);
  1883. cmMemPtrFree(&p->meanV);
  1884. cmMemPtrFree(&p->varV);
  1885. cmObjFree(pp);
  1886. return cmOkRC;
  1887. }
  1888. cmRC_t cmStatsProcInit( cmStatsProc* p, unsigned wndEleCnt, unsigned flags )
  1889. {
  1890. cmRC_t rc;
  1891. if((rc = cmStatsProcFinal(p)) != cmOkRC )
  1892. return rc;
  1893. p->wndEleCnt = wndEleCnt;
  1894. p->dimCnt = 0;
  1895. p->curIdx = 0;
  1896. p->curCnt = 1;
  1897. p->flags = flags;
  1898. p->execCnt = 0;
  1899. p->regArrayN = 0;
  1900. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"statsProc");
  1901. return rc;
  1902. }
  1903. cmRC_t cmStatsProcFinal( cmStatsProc* p )
  1904. {
  1905. if( p != NULL )
  1906. cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  1907. return cmOkRC;
  1908. }
  1909. unsigned cmStatsProcReg( cmStatsProc* p, unsigned featId, unsigned featEleCnt )
  1910. {
  1911. cmStatsProcRecd r;
  1912. r.featId = featId;
  1913. r.idx = p->dimCnt;
  1914. r.cnt = featEleCnt;
  1915. p->dimCnt += featEleCnt;
  1916. //unsigned i;
  1917. // printf("B:\n");
  1918. //for(i=0; i<p->regArrayN; ++i)
  1919. // printf("fid:%i idx:%i cnt:%i : fid:%i cnt:%i\n", p->regArrayV[i].featId,p->regArrayV[i].idx,p->regArrayV[i].cnt,featId,featEleCnt);
  1920. //printf("\nA:\n");
  1921. p->regArrayV = cmMemResizePZ( cmStatsProcRecd, p->regArrayV, p->regArrayN+1 );
  1922. p->regArrayV[ p->regArrayN ] = r;
  1923. p->regArrayN++;
  1924. //for(i=0; i<p->regArrayN; ++i)
  1925. // printf("fid:%i idx:%i cnt:%i : fid:%i cnt:%i\n", p->regArrayV[i].featId,p->regArrayV[i].idx,p->regArrayV[i].cnt,featId,featEleCnt);
  1926. //printf("\n");
  1927. return p->regArrayN-1; // return the index of the new reg recd
  1928. }
  1929. const cmStatsProcRecd* cmStatsProcRecdPtr( cmStatsProc* p, unsigned regId )
  1930. {
  1931. assert( regId < p->regArrayN );
  1932. return p->regArrayV + regId;
  1933. }
  1934. cmRC_t cmStatsProcExecD( cmStatsProc* p, unsigned regId, const double v[], unsigned vCnt )
  1935. {
  1936. cmRC_t rc = cmOkRC;
  1937. // on the first pass allcoate the storage buffer (m) and vectors (sumV,meanV and varV)
  1938. if( p->execCnt == 0 )
  1939. {
  1940. p->sumV = cmMemResizeZ( double, p->sumV, p->dimCnt);
  1941. p->meanV = cmMemResizeZ( double, p->meanV, p->dimCnt );
  1942. p->varV = cmMemResizeZ( double, p->varV, p->dimCnt );
  1943. p->m = cmMemResizeZ( double, p->m, p->dimCnt * p->wndEleCnt );
  1944. }
  1945. // if the storage matrix is full
  1946. if( p->curIdx == p->wndEleCnt )
  1947. return rc;
  1948. // get the pointer to this data source reg recd
  1949. assert( regId < p->regArrayN);
  1950. cmStatsProcRecd* r = p->regArrayV + regId;
  1951. // the dimensionality of the incoming data must be <= the registered dimensionality
  1952. assert( r->cnt <= vCnt );
  1953. unsigned dimIdx = r->idx;
  1954. bool updateFl = cmIsFlag(p->flags,kUpdateOnExecStatProcFl);
  1955. double* sbp = p->sumV + dimIdx; // sum base ptr
  1956. // mbp point to a segment (mbp[vCnt]) in column p->curIdx
  1957. double* mbp = p->m + (p->curIdx * p->dimCnt) + dimIdx; // mem col base ptr
  1958. const double* mep = p->m + p->dimCnt * p->wndEleCnt;
  1959. // decr the current col segment from the sum
  1960. if( updateFl )
  1961. cmVOD_SubVV( sbp, vCnt, mbp );
  1962. assert( p->m <= mbp && mbp < mep && p->m <= mbp+vCnt && mbp+vCnt <= mep );
  1963. // copy in the incoming values to mem col segment
  1964. cmVOD_Copy( mbp, vCnt, v );
  1965. if( updateFl )
  1966. {
  1967. // incr the sum from the incoming value
  1968. cmVOD_AddVV( sbp, vCnt, mbp );
  1969. // use the new sum to compute new mean values
  1970. cmVOD_DivVVS( p->meanV + dimIdx, vCnt, sbp, p->curCnt );
  1971. // update the variance - cmross each row
  1972. unsigned di;
  1973. for(di=dimIdx; di<dimIdx+vCnt; ++di )
  1974. p->varV[di] = cmVOD_VarianceN( p->m + dimIdx, p->curCnt, p->dimCnt, p->meanV + dimIdx );
  1975. }
  1976. ++p->execCnt;
  1977. return cmOkRC;
  1978. }
  1979. cmRC_t cmStatsProcExecF( cmStatsProc* p, unsigned regId, const float v[], unsigned vCnt )
  1980. {
  1981. double dv[ vCnt ];
  1982. cmVOD_CopyF(dv,vCnt,v);
  1983. cmStatsProcExecD(p,regId,dv,vCnt);
  1984. return cmOkRC;
  1985. }
  1986. cmRC_t cmStatsProcCalc(cmStatsProc* p )
  1987. {
  1988. unsigned colCnt = cmMin(p->curCnt,p->wndEleCnt);
  1989. unsigned i = 0;
  1990. cmVOD_Fill(p->sumV,p->dimCnt,0);
  1991. // sum the ith col of p->m[] into p->sumV[i]
  1992. for(; i<colCnt; ++i)
  1993. {
  1994. cmVOD_AddVV( p->sumV, p->dimCnt, p->m + (i * p->dimCnt) );
  1995. if( p->mfp != NULL )
  1996. cmMtxFileDoubleExec( p->mfp, p->sumV, p->dimCnt, 1 );
  1997. }
  1998. // calc the mean of each row
  1999. cmVOD_DivVVS( p->meanV, p->dimCnt, p->sumV, colCnt );
  2000. // calc the variance cmross each row
  2001. for(i=0; i<p->dimCnt; ++i)
  2002. p->varV[i] = cmVOD_VarianceN(p->m + i, colCnt, p->dimCnt, p->meanV + i );
  2003. return cmOkRC;
  2004. }
  2005. cmRC_t cmStatsProcAdvance( cmStatsProc* p )
  2006. {
  2007. ++p->curIdx;
  2008. if( p->curIdx > p->wndEleCnt )
  2009. p->curIdx = 0;
  2010. p->curCnt = cmMin(p->curCnt+1,p->wndEleCnt);
  2011. return cmOkRC;
  2012. }
  2013. void cmStatsProcTest( cmVReportFuncPtr_t vReportFunc )
  2014. {
  2015. enum
  2016. {
  2017. wndEleCnt = 7,
  2018. dDimCnt = 3,
  2019. fDimCnt = 2,
  2020. dimCnt = dDimCnt + fDimCnt,
  2021. kTypeId0 = 0,
  2022. kTypeId1 = 1
  2023. };
  2024. unsigned flags = 0;
  2025. unsigned i;
  2026. double dd[ dDimCnt * wndEleCnt ] =
  2027. {
  2028. 0, 1, 2,
  2029. 3, 4, 5,
  2030. 6, 7, 8,
  2031. 9, 10, 11,
  2032. 12, 13, 14,
  2033. 15, 16, 17,
  2034. 18, 19, 20
  2035. };
  2036. float fd[ 14 ] =
  2037. {
  2038. 0, 1,
  2039. 2, 3,
  2040. 4, 5,
  2041. 6, 7,
  2042. 8, 9,
  2043. 10, 11,
  2044. 12, 13
  2045. };
  2046. cmCtx c;
  2047. cmCtxInit(&c, vReportFunc, vReportFunc, NULL );
  2048. cmStatsProc* p = cmStatsProcAlloc( &c, NULL, wndEleCnt, flags );
  2049. unsigned regId0 = cmStatsProcReg( p, kTypeId0, dDimCnt );
  2050. unsigned regId1 = cmStatsProcReg( p, kTypeId1, fDimCnt );
  2051. for(i=0; i<wndEleCnt; ++i)
  2052. {
  2053. cmStatsProcExecD( p, regId0, dd + (i*dDimCnt), dDimCnt );
  2054. cmStatsProcExecF( p, regId1, fd + (i*fDimCnt), fDimCnt );
  2055. cmStatsProcAdvance(p);
  2056. }
  2057. cmStatsProcCalc( p);
  2058. cmVOD_PrintE( vReportFunc, 1, p->dimCnt, p->meanV );
  2059. cmVOD_PrintE( vReportFunc, 1, p->dimCnt, p->varV );
  2060. cmStatsProcFree(&p);
  2061. }
  2062. */
  2063. //------------------------------------------------------------------------------------------------------------
  2064. cmBeatHist* cmBeatHistAlloc( cmCtx* c, cmBeatHist* ap, unsigned frmCnt )
  2065. {
  2066. cmBeatHist* p = cmObjAlloc(cmBeatHist,c,ap);
  2067. p->fft = cmFftAllocRR(c,NULL,NULL,0,kToPolarFftFl);
  2068. p->ifft = cmIFftAllocRR(c,NULL,0);
  2069. if( frmCnt > 0 )
  2070. if( cmBeatHistInit(p,frmCnt) != cmOkRC )
  2071. cmBeatHistFree(&p);
  2072. return p;
  2073. }
  2074. cmRC_t cmBeatHistFree( cmBeatHist** pp )
  2075. {
  2076. cmRC_t rc = cmOkRC;
  2077. cmBeatHist* p = *pp;
  2078. if( pp == NULL || *pp == NULL )
  2079. return cmOkRC;
  2080. if((rc = cmBeatHistFinal(p)) != cmOkRC )
  2081. return rc;
  2082. cmMemPtrFree(&p->m);
  2083. cmMemPtrFree(&p->H);
  2084. cmMemPtrFree(&p->df);
  2085. cmMemPtrFree(&p->fdf);
  2086. cmMemPtrFree(&p->histV);
  2087. cmFftFreeRR(&p->fft);
  2088. cmIFftFreeRR(&p->ifft);
  2089. cmObjFree(&p);
  2090. return rc;
  2091. }
  2092. void _cmBeatHistInitH( cmReal_t* H, unsigned hrn, unsigned hcn, unsigned ri, unsigned c0, unsigned c1 )
  2093. {
  2094. unsigned ci;
  2095. for(ci=c0; ci<=c1; ++ci)
  2096. H[ (ci*hrn) + ri ] = 1;
  2097. }
  2098. cmRC_t cmBeatHistInit( cmBeatHist* p, unsigned frmCnt )
  2099. {
  2100. cmRC_t rc;
  2101. unsigned i,j,k;
  2102. enum { kLagFact = 4, kHistBinCnt=15, kHColCnt=128 };
  2103. if((rc = cmBeatHistFinal(p)) != cmOkRC )
  2104. return rc;
  2105. p->frmCnt = frmCnt;
  2106. p->maxLagCnt = (unsigned)floor(p->frmCnt / kLagFact);
  2107. p->histBinCnt= kHistBinCnt;
  2108. p->hColCnt = kHColCnt;
  2109. p->dfi = 0;
  2110. unsigned cfbMemN = p->frmCnt * p->maxLagCnt;
  2111. unsigned hMemN = p->histBinCnt * kHColCnt;
  2112. //cmArrayResizeVZ(p->obj.ctx,&p->cfbMem, cmReal_t, &p->m, cfbMemN, &p->H, hMemN, NULL);
  2113. p->m = cmMemResizeZ( cmReal_t, p->m, cfbMemN );
  2114. p->H = cmMemResizeZ( cmReal_t, p->H, hMemN );
  2115. //p->df = cmArrayResizeZ(c,&p->dfMem, 2*p->frmCnt + kHistBinCnt, cmReal_t);
  2116. //p->fdf = p->df + p->frmCnt;
  2117. //p->histV = p->fdf + p->frmCnt;
  2118. //cmArrayResizeVZ(p->obj.ctx, &p->dfMem, cmReal_t, &p->df, p->frmCnt, &p->fdf, p->frmCnt, &p->histV, kHistBinCnt, NULL );
  2119. p->df = cmMemResizeZ( cmReal_t, p->df, p->frmCnt );
  2120. p->fdf = cmMemResizeZ( cmReal_t, p->fdf, p->frmCnt );
  2121. p->histV = cmMemResizeZ( cmReal_t, p->histV, kHistBinCnt );
  2122. cmFftInitRR( p->fft,NULL,cmNextPowerOfTwo(2*frmCnt),kToPolarFftFl);
  2123. cmIFftInitRR(p->ifft,p->fft->binCnt);
  2124. // initialize H
  2125. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 0, 103, 127 );
  2126. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 1, 86, 102 );
  2127. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 2, 73, 85 );
  2128. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 3, 64, 72 );
  2129. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 4, 57, 63 );
  2130. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 5, 51, 56 );
  2131. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 6, 46, 50 );
  2132. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 7, 43, 45 );
  2133. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 8, 39, 42 );
  2134. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 9, 36, 38 );
  2135. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 10,32, 35 );
  2136. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 11,28, 31 );
  2137. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 12,25, 27 );
  2138. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 13,21, 24 );
  2139. _cmBeatHistInitH( p->H, p->histBinCnt, p->hColCnt, 14,11, 20 );
  2140. // for each column
  2141. for(i=0; i<p->maxLagCnt; ++i)
  2142. {
  2143. // for each lag group
  2144. for(j=0; j<kLagFact; ++j)
  2145. {
  2146. for(k=0; k<=2*j; ++k)
  2147. {
  2148. unsigned idx = (i*p->frmCnt) + (i*j) + i + k;
  2149. if( idx < cfbMemN )
  2150. p->m[ idx ] = 1.0/(2*j+1);
  2151. }
  2152. }
  2153. }
  2154. double g[ p->maxLagCnt ];
  2155. double g_max = 0;
  2156. double b = 43;
  2157. b = b*b;
  2158. for(i=0; i<p->maxLagCnt; ++i)
  2159. {
  2160. double n = i+1;
  2161. g[i] = n/b * exp(-(n*n) / (2*b));
  2162. if( g[i] > g_max )
  2163. g_max = g[i];
  2164. }
  2165. // normalize g[]
  2166. cmVOD_DivVS( g, p->maxLagCnt, g_max );
  2167. // for each column of p->m[]
  2168. for(i=0; i<p->maxLagCnt; ++i)
  2169. {
  2170. double gg = g[i];
  2171. k = i*p->frmCnt;
  2172. for(j=0; j<p->frmCnt; ++j)
  2173. p->m[ k + j ] *= gg;
  2174. }
  2175. //p->mfp = cmCtxAllocDebugFile(p->obj.ctx,"beatHist");
  2176. return cmOkRC;
  2177. }
  2178. cmRC_t cmBeatHistFinal( cmBeatHist* p )
  2179. {
  2180. //if( p != NULL )
  2181. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  2182. return cmOkRC;
  2183. }
  2184. cmRC_t cmBeatHistExec( cmBeatHist* p, cmSample_t df )
  2185. {
  2186. if( p->dfi < p->frmCnt )
  2187. p->df[p->dfi++] = df;
  2188. return cmOkRC;
  2189. }
  2190. cmRC_t cmBeatHistCalc( cmBeatHist* p )
  2191. {
  2192. unsigned i;
  2193. // df -= mean(df)
  2194. cmVOR_SubVS(p->df,p->frmCnt,cmVOR_Mean(p->df,p->frmCnt));
  2195. //cmPlotLineR( "dfm", NULL, p->df, NULL, p->frmCnt, NULL, kSolidPlotLineId );
  2196. // take alpha norm of df
  2197. double alpha = 9;
  2198. cmVOR_DivVS(p->df,p->frmCnt, cmVOR_AlphaNorm(p->df,p->frmCnt,alpha));
  2199. //cmPlotLineS( "dfd", NULL, p->df, NULL, p->frmCnt, NULL, kSolidPlotLineId );
  2200. // low pass forward/backward filter df[] into fdf[]
  2201. cmReal_t b[] = {0.1600, 0.3200, 0.1600};
  2202. unsigned bn = sizeof(b)/sizeof(b[0]);
  2203. cmReal_t a[] = {1.0000, -0.5949, 0.2348};
  2204. unsigned an = sizeof(a)/sizeof(a[0]);
  2205. cmFilterFilterR(p->obj.ctx,b,bn,a,an,p->df,p->frmCnt,p->fdf,p->frmCnt);
  2206. //cmPlotLineS( "fdf", NULL, p->fdf, NULL, p->frmCnt, NULL, kSolidPlotLineId );
  2207. // median filter to low-passed filtered fdf[] into df[]
  2208. cmVOR_FnThresh(p->fdf,p->frmCnt,16,p->df,1,NULL);
  2209. // subtract med filtered signal from the low pa1ssed signal.
  2210. // fdf[] -= df[];
  2211. cmVOR_SubVV(p->fdf,p->frmCnt,p->df);
  2212. // half-wave rectify fdf[] = set all negative values in fdf[] to zero.
  2213. cmVOR_HalfWaveRectify(p->fdf,p->frmCnt,p->fdf);
  2214. //cmPlotLineS( "meddf", NULL, p->fdf, NULL, p->frmCnt, NULL, kSolidPlotLineId );
  2215. // take FT of fdf[]
  2216. cmFftExecRR(p->fft,p->fdf,p->frmCnt);
  2217. // square FT magn.
  2218. cmVOR_PowVS(p->fft->magV,p->fft->binCnt,2);
  2219. //cmPlotLineS( "mag", NULL, p->fft->magV, NULL, p->fft->binCnt, NULL, kSolidPlotLineId );
  2220. // take the IFFT of the squared magnitude vector.
  2221. cmVOR_Fill(p->fft->phsV,p->fft->binCnt,0);
  2222. cmIFftExecRectRR(p->ifft,p->fft->magV,p->fft->phsV);
  2223. // Matlab automatically provides this scaling as part of the IFFT.
  2224. cmVOR_DivVS(p->ifft->outV,p->ifft->outN,p->ifft->outN);
  2225. // remove bias for short periods from CMF
  2226. for(i=0; i<p->frmCnt; ++i)
  2227. p->ifft->outV[i] /= (p->frmCnt - i);
  2228. //cmPlotLineS( "cm", NULL, p->ifft->outV, NULL, p->frmCnt, NULL, kSolidPlotLineId );
  2229. // apply comb filter to the CMF and store result in df[maxLagCnt]
  2230. cmVOR_MultVMtV(p->df,p->maxLagCnt,p->m,p->frmCnt,p->ifft->outV);
  2231. //acPlotLineS( "cfb", NULL, p->df, NULL, p->maxLagCnt, NULL, kSolidPlotLineId );
  2232. //acVOR_Print(p->obj.err.rpt,1,p->maxLagCnt,p->df);
  2233. assert( p->maxLagCnt == p->hColCnt );
  2234. cmVOR_MultVMV(p->histV,p->histBinCnt,p->H,p->hColCnt,p->df);
  2235. cmReal_t bins[] = { 25, 17, 13, 9, 7, 6, 5, 3, 4, 3, 4, 4, 3, 4, 10};
  2236. cmVOR_DivVV( p->histV, p->histBinCnt, bins );
  2237. //cmPlotLineS( "cfb", NULL, p->histV, NULL, p->histBinCnt, NULL, kSolidPlotLineId );
  2238. if( p->mfp != NULL )
  2239. cmMtxFileRealExec( p->mfp, p->histV, p->histBinCnt );
  2240. return cmOkRC;
  2241. }
  2242. //------------------------------------------------------------------------------------------------------------
  2243. cmGmm_t* cmGmmAlloc( cmCtx* c, cmGmm_t* ap, unsigned K, unsigned D, const cmReal_t* gM, const cmReal_t* uM, const cmReal_t* sMM, unsigned uflags )
  2244. {
  2245. cmGmm_t* p = cmObjAlloc( cmGmm_t, c, ap );
  2246. if( K > 0 && D > 0 )
  2247. if( cmGmmInit(p,K,D,gM,uM,sMM,uflags) != cmOkRC )
  2248. cmGmmFree(&p);
  2249. return p;
  2250. }
  2251. cmRC_t cmGmmFree( cmGmm_t** pp )
  2252. {
  2253. cmRC_t rc = cmOkRC;
  2254. cmGmm_t* p = *pp;
  2255. if( pp == NULL || *pp == NULL )
  2256. return cmOkRC;
  2257. if((rc = cmGmmFinal(p)) != cmOkRC )
  2258. return rc;
  2259. cmMemPtrFree(&p->gV);
  2260. cmMemPtrFree(&p->uM);
  2261. cmMemPtrFree(&p->sMM);
  2262. cmMemPtrFree(&p->isMM);
  2263. cmMemPtrFree(&p->uMM);
  2264. cmMemPtrFree(&p->logDetV);
  2265. cmMemPtrFree(&p->t);
  2266. cmObjFree(pp);
  2267. return rc;
  2268. }
  2269. cmRC_t _cmGmmUpdateCovar( cmGmm_t* p, const cmReal_t* sMM )
  2270. {
  2271. unsigned i;
  2272. if( sMM == NULL )
  2273. return cmOkRC;
  2274. unsigned De2 = p->D*p->D;
  2275. unsigned KDe2 = p->K*De2;
  2276. cmVOR_Copy(p->sMM, KDe2, sMM);
  2277. cmVOR_Copy(p->isMM,KDe2, sMM);
  2278. cmVOR_Copy(p->uMM, KDe2, sMM);
  2279. //if( cmIsFlag(p->uflags,cmGmmCovarNoProcFl) )
  2280. // return cmOkRC;
  2281. // for each component
  2282. for(i=0; i<p->K; ++i)
  2283. {
  2284. cmReal_t* is = p->isMM + i*De2;
  2285. cmReal_t* u = p->uMM + i*De2;
  2286. cmReal_t* r;
  2287. // if the covariance matrix is diagnal
  2288. if( cmIsFlag(p->uflags,cmGmmDiagFl))
  2289. {
  2290. p->logDetV[i] = cmVOR_LogDetDiagM(is,p->D); // calc the det. of diag. covar. mtx
  2291. r = cmVOR_InvDiagM(is,p->D); // calc the inverse in place
  2292. }
  2293. else
  2294. {
  2295. p->logDetV[i] = cmVOR_LogDetM(is,p->D); // calc the det. of covar mtx
  2296. r = cmVOR_InvM(is,p->D); // calc the inverse in place
  2297. }
  2298. if( fabs(p->logDetV[i]) < 1e-20 )
  2299. {
  2300. cmCtxPrint(p->obj.ctx,"%i\n",i);
  2301. cmVOR_PrintLE("DANGER SM:\n",p->obj.err.rpt,p->D,p->D,p->sMM);
  2302. }
  2303. if( cmVOR_CholZ(u,p->D) == NULL )
  2304. {
  2305. return cmCtxRtCondition(&p->obj, cmSingularMtxRC, "A singular covariance matrix (Cholesky factorization failed.) was encountered in _cmGmmUpdateCovar().");
  2306. }
  2307. if( p->logDetV[i] == 0 )
  2308. {
  2309. cmGmmPrint(p,true);
  2310. return cmCtxRtCondition(&p->obj, cmSingularMtxRC, "A singular covariance matrix (det==0) was encountered in _cmGmmUpdateCovar().");
  2311. }
  2312. if( r == NULL )
  2313. {
  2314. //cmCtxPrint(c,"%i\n",i);
  2315. //cmVOR_PrintLE("DANGER SM:\n",p->obj.err.rpt,p->D,p->D,p->sMM);
  2316. return cmCtxRtCondition(&p->obj, cmSingularMtxRC, "A singular covariance matrix (inversion failed) was encountered in _cmGmmUpdateCovar().");
  2317. }
  2318. }
  2319. return cmOkRC;
  2320. }
  2321. cmRC_t cmGmmInit( cmGmm_t* p, unsigned K, unsigned D, const cmReal_t* gV, const cmReal_t* uM, const cmReal_t* sMM, unsigned uflags )
  2322. {
  2323. cmRC_t rc;
  2324. if((rc = cmGmmFinal(p)) != cmOkRC )
  2325. return rc;
  2326. // gM[K] uM[DK] sMM[DDK] isMM[DDK]+ uMM[DDK] logDetV[K] t[DD] fact[K]
  2327. /*
  2328. unsigned n = K + (D*K) + (D*D*K) + (D*D*K) + (D*D*K) + K + (D*D) + K;
  2329. p->gV = cmArrayResizeZ(c,&p->memA, n, cmReal_t );
  2330. p->uM = p->gV + K;
  2331. p->sMM = p->uM + (D*K);
  2332. p->isMM = p->sMM + (D*D*K);
  2333. p->uMM = p->isMM + (D*D*K);
  2334. p->logDetV = p->uMM + (D*D*K);
  2335. p->t = p->logDetV + K;
  2336. */
  2337. //cmArrayResizeVZ(c, &p->memA, cmReal_t, &p->gV,K, &p->uM,D*K, &p->sMM,D*D*K,
  2338. //&p->isMM,D*D*K, &p->uMM,D*D*K, &p->logDetV,K, &p->t,D*D, NULL );
  2339. p->gV = cmMemResizeZ( cmReal_t, p->gV, K );
  2340. p->uM = cmMemResizeZ( cmReal_t, p->uM, D*K);
  2341. p->sMM = cmMemResizeZ( cmReal_t, p->sMM, D*D*K);
  2342. p->isMM = cmMemResizeZ( cmReal_t, p->isMM, D*D*K);
  2343. p->uMM = cmMemResizeZ( cmReal_t, p->uMM, D*D*K);
  2344. p->logDetV = cmMemResizeZ( cmReal_t, p->logDetV, K);
  2345. p->t = cmMemResizeZ( cmReal_t, p->t, D*D );
  2346. p->K = K;
  2347. p->D = D;
  2348. p->uflags = uflags;
  2349. if( gV != NULL )
  2350. cmVOR_Copy(p->gV,K,gV);
  2351. if( uM != NULL )
  2352. cmVOR_Copy(p->uM,D*K,uM);
  2353. return _cmGmmUpdateCovar(p,sMM );
  2354. }
  2355. cmRC_t cmGmmFinal( cmGmm_t* p )
  2356. { return cmOkRC; }
  2357. typedef struct
  2358. {
  2359. cmGmm_t* p;
  2360. const cmReal_t* xM;
  2361. unsigned colCnt;
  2362. } _cmGmmRdFuncData_t;
  2363. const cmReal_t* _cmGmmReadFunc( void* userPtr, unsigned colIdx )
  2364. {
  2365. assert(colIdx < ((const _cmGmmRdFuncData_t*)userPtr)->colCnt);
  2366. return ((const _cmGmmRdFuncData_t*)userPtr)->xM + (colIdx * ((const _cmGmmRdFuncData_t*)userPtr)->p->D);
  2367. }
  2368. // xM[D,xN]
  2369. // yV[xN]
  2370. // yM[xN,K]
  2371. cmRC_t cmGmmEval( cmGmm_t* p, const cmReal_t* xM, unsigned xN, cmReal_t* yV, cmReal_t* yM )
  2372. {
  2373. _cmGmmRdFuncData_t r;
  2374. r.colCnt = xN;
  2375. r.p = p;
  2376. r.xM = xM;
  2377. return cmGmmEval2(p,_cmGmmReadFunc,&r,xN,yV,yM);
  2378. }
  2379. cmRC_t cmGmmEval2( cmGmm_t* p, cmGmmReadFunc_t readFunc, void* userFuncPtr, unsigned xN, cmReal_t* yV, cmReal_t* yM)
  2380. {
  2381. cmReal_t tV[xN];
  2382. unsigned k;
  2383. //cmVOR_PrintL("cV: ",p->obj.err.rpt, 1, p->K, p->gV);
  2384. //cmVOR_PrintL("uM:\n",p->obj.err.rpt, p->D, p->K, p->uM );
  2385. //
  2386. cmVOR_Fill(yV,xN,0);
  2387. // for each component PDF
  2388. for(k=0; k<p->K; k++)
  2389. {
  2390. const cmReal_t* meanV = p->uM + (k*p->D);
  2391. const cmReal_t* isM = p->isMM + (k*p->D*p->D);
  2392. cmReal_t* pV;
  2393. if( yM == NULL )
  2394. pV = tV;
  2395. else
  2396. pV = yM + (k*xN);
  2397. // evaluate the kth component PDF with xM[1:T]
  2398. //cmVOR_MultVarGaussPDF2( pV, xM, meanV, isM, p->logDetV[k], p->D, xN, cmIsFlag(p->uflags,cmGmmDiagFl) );
  2399. cmVOR_MultVarGaussPDF3( pV, readFunc, userFuncPtr, meanV, isM, p->logDetV[k], p->D, xN, cmIsFlag(p->uflags,cmGmmDiagFl) );
  2400. // apply the kth component weight
  2401. cmVOR_MultVS( pV, xN, p->gV[k] );
  2402. // sum the result into the output vector
  2403. cmVOR_AddVV( yV, xN, pV );
  2404. }
  2405. return cmOkRC;
  2406. }
  2407. // Evaluate each component for a single data point
  2408. // xV[D] - observed data point
  2409. // yV[K] - output contains the evaluation for each component
  2410. cmRC_t cmGmmEval3( cmGmm_t* p, const cmReal_t* xV, cmReal_t* yV )
  2411. {
  2412. unsigned k;
  2413. for(k=0; k<p->K; ++k)
  2414. {
  2415. const cmReal_t* meanV = p->uM + (k*p->D);
  2416. const cmReal_t* isM = p->isMM + (k*p->D*p->D);
  2417. // evaluate the kth component PDF with xM[1:T]
  2418. cmVOR_MultVarGaussPDF2( yV + k, xV, meanV, isM, p->logDetV[k], p->D, 1, cmIsFlag(p->uflags,cmGmmDiagFl) );
  2419. // apply the kth component weight
  2420. yV[k] *= p->gV[k];
  2421. }
  2422. return cmOkRC;
  2423. }
  2424. cmReal_t _cmGmmKmeansDistFunc( void* userPtr, const cmReal_t* v0, const cmReal_t* v1, unsigned vn )
  2425. { return cmVOR_EuclidDistance(v0,v1,vn); }
  2426. cmRC_t cmGmmRandomize2( cmGmm_t* p, cmGmmReadFunc_t readFunc, void* funcUserPtr, unsigned xN, const cmReal_t* uM, const bool* roFlV )
  2427. {
  2428. unsigned k;
  2429. unsigned iV[ p->K ];
  2430. if( uM == NULL )
  2431. roFlV = NULL;
  2432. // randomize the mixture coefficients
  2433. cmVOR_Random( p->gV, p->K, 0.0, 1.0 );
  2434. cmVOR_NormalizeProbability(p->gV,p->K);
  2435. // fill iV with random integers between 0 and xN-1
  2436. cmVOU_Random( iV, p->K, xN-1 );
  2437. // for each component
  2438. for(k=0; k<p->K; ++k)
  2439. {
  2440. cmReal_t r[ p->D ];
  2441. // if this component's mean is not read-only
  2442. if( roFlV==NULL || roFlV[k]==false )
  2443. {
  2444. const cmReal_t* xV = NULL;
  2445. if( uM == NULL )
  2446. xV = readFunc( funcUserPtr, iV[k] ); // read a random frame index
  2447. else
  2448. xV = uM + (k*p->D); // select a user supplied mean vector
  2449. assert( xV != NULL );
  2450. // set the random feature vector as this components mean value
  2451. cmVOR_Copy(p->uM+(k*p->D),p->D,xV);
  2452. }
  2453. cmReal_t* sM = p->sMM+(k*p->D*p->D);
  2454. // create a random covariance mtx
  2455. if( cmIsFlag(p->uflags,cmGmmDiagFl) )
  2456. {
  2457. // create a random diag. covar mtx
  2458. cmVOR_Random(r,p->D,0.0,1.0);
  2459. cmVOR_Diag(sM,p->D,r);
  2460. }
  2461. else
  2462. {
  2463. // create a random symetric positive definite matrix
  2464. cmVOR_RandSymPosDef(sM,p->D,p->t);
  2465. }
  2466. }
  2467. unsigned* classIdxV = cmMemAllocZ(unsigned, xN );
  2468. // if some components have read-only mean's
  2469. if( uM != NULL && roFlV != NULL )
  2470. {
  2471. assert( xN >= p->K );
  2472. for(k=0; k<p->K; ++k)
  2473. classIdxV[k] = roFlV[k];
  2474. }
  2475. // use kmeans clustering to move the means closer to their center values
  2476. if( cmIsFlag( p->uflags, cmGmmSkipKmeansFl) == false )
  2477. cmVOR_Kmeans2( classIdxV, p->uM, p->K, readFunc, p->D, xN, funcUserPtr, _cmGmmKmeansDistFunc, NULL, -1, 0 );
  2478. cmMemPtrFree(&classIdxV);
  2479. return _cmGmmUpdateCovar(p,p->sMM);
  2480. }
  2481. cmRC_t cmGmmRandomize( cmGmm_t* p, const cmReal_t* xM, unsigned xN )
  2482. {
  2483. _cmGmmRdFuncData_t r;
  2484. r.colCnt = xN;
  2485. r.p = p;
  2486. r.xM = xM;
  2487. return cmGmmRandomize2(p,_cmGmmReadFunc,&r,xN,NULL,NULL);
  2488. }
  2489. // xM[D,xN]
  2490. cmRC_t cmGmmTrain( cmGmm_t* p, const cmReal_t* xM, unsigned xN, unsigned* iterCntPtr )
  2491. {
  2492. unsigned i,k;
  2493. cmRC_t rc;
  2494. if((rc = cmGmmRandomize(p,xM,xN)) != cmOkRC )
  2495. return rc;
  2496. //cmGmmPrint(c,p);
  2497. // wM[xN,K]
  2498. cmReal_t wM[ xN * p->K ]; // wM[N,K] soft assignment mtx
  2499. unsigned wV[ xN ]; // wV[N] hard assignment vector
  2500. unsigned stopCnt = 0;
  2501. unsigned curStopCnt = 0;
  2502. if( iterCntPtr != NULL )
  2503. {
  2504. stopCnt = *iterCntPtr;
  2505. *iterCntPtr = 0;
  2506. }
  2507. else
  2508. {
  2509. // BUG BUG BUG
  2510. // stopCnt is used uninitialized when iterCntPtr == NULL
  2511. assert( 0 );
  2512. }
  2513. while(1)
  2514. {
  2515. //cmVOR_NormalizeProbability(p->gV,p->K);
  2516. cmCtxPrint(p->obj.ctx,"iter:%i --------------------------------------------\n",*iterCntPtr );
  2517. cmVOR_PrintL("uM:\n", p->obj.err.rpt, p->D, p->K, p->uM );
  2518. cmVOR_PrintL("gV:\n", p->obj.err.rpt, 1, p->K, p->gV );
  2519. //cmGmmPrint(c,p);
  2520. for(k=0; k<p->K; ++k)
  2521. {
  2522. cmReal_t* wp = wM + (k*xN);
  2523. // calc the prob that each data point in xM[] was generated by the kth gaussian
  2524. // and store as a column vector in wM[:,k]
  2525. cmVOR_MultVarGaussPDF2( wp, xM, p->uM + (k*p->D), p->isMM + (k*p->D*p->D), p->logDetV[k], p->D, xN, cmIsFlag(p->uflags,cmGmmDiagFl) );
  2526. // scale the prob by the gain coeff for gaussian k
  2527. cmVOR_MultVS( wp, xN, p->gV[k]);
  2528. }
  2529. //cmVOR_PrintL("wM:\n",p->obj.err.rpt,xN,p->K,wM);
  2530. bool doneFl = true;
  2531. for(i=0; i<xN; ++i)
  2532. {
  2533. // form a probability for the ith data point weights
  2534. cmVOR_NormalizeProbabilityN( wM + i, p->K, xN);
  2535. // select the cluster to which the ith data point is most likely to belong
  2536. unsigned mi = cmVOR_MaxIndex(wM + i, p->K, xN);
  2537. // if the ith data point changed clusters
  2538. if( mi != wV[i] )
  2539. {
  2540. doneFl = false;
  2541. wV[i] = mi;
  2542. }
  2543. }
  2544. curStopCnt = doneFl ? curStopCnt+1 : 0;
  2545. // if no data points changed owners then the clustering is complete
  2546. if( curStopCnt == stopCnt )
  2547. {
  2548. //cmVOU_PrintL("wV: ",p->obj.err.rpt,xN,1,wV);
  2549. break;
  2550. }
  2551. // for each cluster
  2552. for(k=0; k<p->K; ++k)
  2553. {
  2554. cmReal_t* uV = p->uM + (k*p->D); // meanV[k]
  2555. cmReal_t* sM = p->sMM + (k*p->D*p->D); // covarM[k]
  2556. cmReal_t sw = cmVOR_Sum(wM + (k*xN), xN );
  2557. // update the kth weight
  2558. p->gV[k] = sw / xN;
  2559. // form a sum of all data points weighted by their soft assignment to cluster k
  2560. cmReal_t sumV[p->D];
  2561. cmVOR_MultVMV( sumV, p->D, xM, xN, wM + k*xN );
  2562. // update the mean[k]
  2563. cmVOR_DivVVS(uV, p->D, sumV, sw );
  2564. // update the covar[k]
  2565. // sM += ( W(i,k) .* ((X(:,i) - uV) * (X(:,i) - uV)'));
  2566. cmVOR_Fill(sM,p->D*p->D,0);
  2567. for(i=0; i<xN; ++i)
  2568. {
  2569. cmReal_t duV[ p->D ];
  2570. cmVOR_SubVVV( duV, p->D, xM + (i*p->D), uV ); // duV[] = xM[:,i] - uV[];
  2571. cmVOR_MultMMM( p->t, p->D, p->D, duV, duV, 1 ); // t[,] = duV[] * duV[]'
  2572. cmVOR_MultVS( p->t, p->D*p->D, wM[ k * xN + i ]); // t[,] *= wM[i,k]
  2573. cmVOR_AddVV( sM, p->D*p->D, p->t ); // sM[,] += t[,];
  2574. }
  2575. cmVOR_DivVS( sM, p->D*p->D, sw ); // sM[,] ./ sw;
  2576. }
  2577. // update the inverted covar mtx and covar det.
  2578. if((rc = _cmGmmUpdateCovar(p,p->sMM )) != cmOkRC )
  2579. return rc;
  2580. if( iterCntPtr != NULL )
  2581. *iterCntPtr += 1;
  2582. }
  2583. return cmOkRC;
  2584. }
  2585. // xM[D,xN]
  2586. cmRC_t cmGmmTrain2( cmGmm_t* p, cmGmmReadFunc_t readFunc, void* userFuncPtr, unsigned xN, unsigned* iterCntPtr, const cmReal_t* uM, const bool* roFlV, int maxIterCnt )
  2587. {
  2588. unsigned i,j,k;
  2589. cmRC_t rc;
  2590. // if uM[] is not set then ignore roFlV[]
  2591. if( uM == NULL )
  2592. roFlV=NULL;
  2593. if((rc = cmGmmRandomize2(p,readFunc,userFuncPtr,xN,uM,roFlV)) != cmOkRC )
  2594. return rc;
  2595. //cmGmmPrint(c,p);
  2596. // wM[xN,K] soft assignment mtx
  2597. cmReal_t* wM = cmMemAlloc(cmReal_t, xN * p->K );
  2598. // wV[N] hard assignment vector
  2599. unsigned* wV = cmMemAlloc(unsigned, xN );
  2600. unsigned stopCnt = 0;
  2601. unsigned curStopCnt = 0;
  2602. if( iterCntPtr != NULL )
  2603. {
  2604. stopCnt = *iterCntPtr;
  2605. *iterCntPtr = 0;
  2606. }
  2607. else
  2608. {
  2609. // BUG BUG BUG
  2610. // stopCnt is used uninitialized when iterCntPtr == NULL
  2611. assert( 0 );
  2612. }
  2613. while(1)
  2614. {
  2615. //cmCtxPrint(p->obj.ctx,"iter:%i --------------------------------------------\n",*iterCntPtr );
  2616. //cmVOR_PrintL("uM:\n", p->obj.err.rpt, p->D, p->K, p->uM );
  2617. cmVOR_PrintL("gV:\n", p->obj.err.rpt, 1, p->K, p->gV );
  2618. //cmGmmPrint(c,p);
  2619. for(k=0; k<p->K; ++k)
  2620. {
  2621. cmReal_t* wp = wM + (k*xN);
  2622. // calc the prob that each data point in xM[] was generated by the kth gaussian
  2623. // and store as a column vector in wM[:,k]
  2624. cmVOR_MultVarGaussPDF3( wp, readFunc, userFuncPtr, p->uM + (k*p->D), p->isMM + (k*p->D*p->D), p->logDetV[k], p->D, xN, cmIsFlag(p->uflags,cmGmmDiagFl) );
  2625. // scale the prob by the gain coeff for gaussian k
  2626. cmVOR_MultVS( wp, xN, p->gV[k]);
  2627. }
  2628. //cmVOR_PrintL("wM:\n",p->obj.err.rpt,xN,p->K,wM);
  2629. bool doneFl = true;
  2630. unsigned changeCnt = 0;
  2631. for(i=0; i<xN; ++i)
  2632. {
  2633. // form a probability for the ith data point weights
  2634. cmVOR_NormalizeProbabilityN( wM + i, p->K, xN);
  2635. // select the cluster to which the ith data point is most likely to belong
  2636. unsigned mi = cmVOR_MaxIndex(wM + i, p->K, xN);
  2637. // if the ith data point changed clusters
  2638. if( mi != wV[i] )
  2639. {
  2640. ++changeCnt;
  2641. doneFl = false;
  2642. wV[i] = mi;
  2643. }
  2644. }
  2645. curStopCnt = doneFl ? curStopCnt+1 : 0;
  2646. printf("%i stopCnt:%i changeCnt:%i\n",*iterCntPtr,curStopCnt,changeCnt);
  2647. // if no data points changed owners then the clustering is complete
  2648. if( curStopCnt == stopCnt )
  2649. {
  2650. //cmVOU_PrintL("wV: ",p->obj.err.rpt,xN,1,wV);
  2651. break;
  2652. }
  2653. // if a maxIterCnt was given and the cur iter cnt exceeds the max iter cnt then stop
  2654. if( maxIterCnt>=1 && *iterCntPtr >= maxIterCnt )
  2655. break;
  2656. // form a sum of all data points weighted by their soft assignment to cluster k
  2657. // NOTE: cmGmmTrain() performs this step more efficiently because it use
  2658. // an LAPACK matrix multiply.
  2659. cmReal_t sumM[ p->D * p->K ];
  2660. cmVOR_Zero(sumM,p->D*p->K);
  2661. for(i=0; i<xN; ++i)
  2662. {
  2663. const cmReal_t* xV = readFunc( userFuncPtr, i );
  2664. assert( xV != NULL );
  2665. for(k=0; k<p->K; ++k)
  2666. {
  2667. cmReal_t weight = wM[ i + (k*xN)];
  2668. for(j=0; j<p->D; ++j)
  2669. sumM[ j + (k*p->D) ] += xV[j] * weight;
  2670. }
  2671. }
  2672. // for each cluster that is not marked as read-only
  2673. for(k=0; k<p->K; ++k)
  2674. {
  2675. cmReal_t* uV = p->uM + (k*p->D); // meanV[k]
  2676. cmReal_t* sM = p->sMM + (k*p->D*p->D); // covarM[k]
  2677. cmReal_t sw = cmVOR_Sum(wM + (k*xN), xN );
  2678. // update the kth weight
  2679. p->gV[k] = sw / xN;
  2680. // if this component's mean is not read-only
  2681. if( (roFlV==NULL || roFlV[k]==false) && sw != 0)
  2682. {
  2683. // get vector of all data points weighted by their soft assignment to cluster k
  2684. cmReal_t* sumV = sumM + (k*p->D); // sumV[p->D];
  2685. // update the mean[k]
  2686. cmVOR_DivVVS(uV, p->D, sumV, sw );
  2687. }
  2688. // update the covar[k]
  2689. // sM += ( W(i,k) .* ((X(:,i) - uV) * (X(:,i) - uV)'));
  2690. cmVOR_Fill(sM,p->D*p->D,0);
  2691. for(i=0; i<xN; ++i)
  2692. {
  2693. cmReal_t duV[ p->D ];
  2694. const cmReal_t* xV = readFunc( userFuncPtr, i );
  2695. assert( xV != NULL );
  2696. cmVOR_SubVVV( duV, p->D, xV, uV ); // duV[] = xM[:,i] - uV[];
  2697. cmVOR_MultMMM( p->t, p->D, p->D, duV, duV, 1 ); // t[,] = duV[] * duV[]'
  2698. cmVOR_MultVS( p->t, p->D*p->D, wM[ k * xN + i ]); // t[,] *= wM[i,k]
  2699. cmVOR_AddVV( sM, p->D*p->D, p->t ); // sM[,] += t[,];
  2700. }
  2701. if( sw != 0 )
  2702. cmVOR_DivVS( sM, p->D*p->D, sw ); // sM[,] ./ sw;
  2703. }
  2704. // update the inverted covar mtx and covar det.
  2705. if((rc = _cmGmmUpdateCovar(p,p->sMM )) != cmOkRC )
  2706. goto errLabel;
  2707. if( iterCntPtr != NULL )
  2708. *iterCntPtr += 1;
  2709. }
  2710. cmMemPtrFree(&wM);
  2711. cmMemPtrFree(&wV);
  2712. errLabel:
  2713. return cmOkRC;
  2714. }
  2715. cmRC_t cmGmmTrain3( cmGmm_t* p, const cmReal_t* xM, unsigned xN, unsigned* iterCntPtr )
  2716. {
  2717. _cmGmmRdFuncData_t r;
  2718. r.colCnt = xN;
  2719. r.p = p;
  2720. r.xM = xM;
  2721. return cmGmmTrain2(p,_cmGmmReadFunc,&r,xN,iterCntPtr,NULL,NULL,-1);
  2722. }
  2723. cmRC_t cmGmmGenerate( cmGmm_t* p, cmReal_t* yM, unsigned yN )
  2724. {
  2725. unsigned i=0;
  2726. unsigned kV[yN];
  2727. // use weighted random selection to choose the component for each output value
  2728. cmVOR_WeightedRandInt(kV,yN, p->gV, p->K );
  2729. // cmVOU_Print(p->obj.err.rpt,1,yN,kV);
  2730. for(i=0; i<yN; ++i)
  2731. {
  2732. const cmReal_t* uV = p->uM + (kV[i] * p->D);
  2733. unsigned idx = kV[i] * p->D * p->D;
  2734. //cmVOR_PrintL("sM\n",p->obj.err.rpt,p->D,p->D,sM);
  2735. if( cmIsFlag(p->uflags,cmGmmDiagFl) )
  2736. {
  2737. const cmReal_t* sM = p->sMM + idx;
  2738. cmVOR_RandomGaussDiagM( yM + (i*p->D), p->D, 1, uV, sM );
  2739. }
  2740. else
  2741. {
  2742. const cmReal_t* uM = p->uMM + idx;
  2743. cmVOR_RandomGaussNonDiagM2(yM + (i*p->D), p->D, 1, uV, uM );
  2744. }
  2745. }
  2746. return cmOkRC;
  2747. }
  2748. void cmGmmPrint( cmGmm_t* p, bool fl )
  2749. {
  2750. unsigned k;
  2751. //cmCtx* c = p->obj.ctx;
  2752. cmVOR_PrintL("gV: ", p->obj.err.rpt, 1, p->K, p->gV );
  2753. cmVOR_PrintL("mM:\n", p->obj.err.rpt, p->D, p->K, p->uM );
  2754. for(k=0; k<p->K; ++k)
  2755. cmVOR_PrintL("sM:\n", p->obj.err.rpt, p->D, p->D, p->sMM + (k*p->D*p->D));
  2756. if( fl )
  2757. {
  2758. for(k=0; k<p->K; ++k)
  2759. cmVOR_PrintL("isM:\n", p->obj.err.rpt, p->D, p->D, p->isMM + (k*p->D*p->D));
  2760. for(k=0; k<p->K; ++k)
  2761. cmVOR_PrintL("uM:\n", p->obj.err.rpt, p->D, p->D, p->uMM + (k*p->D*p->D));
  2762. cmVOR_PrintL("logDetV:\n", p->obj.err.rpt, 1, p->K, p->logDetV);
  2763. }
  2764. }
  2765. void cmGmmTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  2766. {
  2767. cmCtx* c = cmCtxAlloc(NULL,rpt,lhH,stH);
  2768. unsigned K = 2;
  2769. unsigned D = 2;
  2770. cmReal_t gV[ 2 ] = { .5, .5 };
  2771. cmReal_t uM[ 4 ] = { .3, .3, .8, .8 };
  2772. cmReal_t sMM[ 8 ] = { .1, 0, 0, .1, .1, 0, 0, .1 };
  2773. unsigned flags = cmGmmDiagFl ;
  2774. unsigned M = 100;
  2775. cmReal_t xM[ D*M ];
  2776. cmReal_t yV[ M ];
  2777. unsigned i,j;
  2778. cmPlotSetup("MultDimGauss Test",1,1);
  2779. cmGmm_t* p = cmGmmAlloc(c, NULL, K, D, gV, uM, sMM, flags );
  2780. if(0)
  2781. {
  2782. cmGmmPrint(p,true);
  2783. for(i=0; i<10; i++)
  2784. for(j=0; j<20; j+=2)
  2785. {
  2786. xM[(i*20)+j] = .1 * i;;
  2787. xM[(i*20)+j + 1] = .1 * (j/2);;
  2788. }
  2789. // octave equivalent
  2790. // x0= .1 * ones(1,10);
  2791. // x = [ 0*x0 1*x0 2*x0 3*x0 4*x0 5*x0 6*x0 7*x0 8*x0 9*x0];
  2792. // x = [x; repmat([0:.1:1],1,10)];
  2793. // y = mvnpdf(x',[.3 .3],[.1 0; 0 .1]); plot(y);
  2794. cmGmmEval(p,xM,M,yV,NULL);
  2795. //cmVOR_PrintL( "xM\n", rpt, D, M, xM );
  2796. cmVOR_PrintL( "yV\n", rpt, 10, 10, yV );
  2797. //printf("y:%f\n",yV[0]);
  2798. cmPlotLineD( NULL, NULL, yV, NULL, M, NULL, kSolidPlotLineId );
  2799. }
  2800. if(0)
  2801. {
  2802. cmReal_t yM[ D*M ];
  2803. cmReal_t yMt[ M*D ];
  2804. cmReal_t uMt[ p->K*D];
  2805. unsigned iterCnt = 10;
  2806. //srand( time(NULL) );
  2807. cmGmmGenerate( p, yM, M );
  2808. p->uflags = 0; // turn off diagonal condition
  2809. if( cmGmmTrain3( p, yM, M, &iterCnt ) != cmOkRC )
  2810. return;
  2811. cmCtxPrint(c,"iterCnt:%i\n",iterCnt);
  2812. cmGmmPrint( p, true );
  2813. cmVOR_Transpose(yMt, yM, D, M );
  2814. //cmVOR_PrintL("yMt\n",vReportFunc,M,D,yMt);
  2815. cmPlotLineD(NULL, yMt, yMt+M, NULL, M, "blue", kAsteriskPlotPtId );
  2816. cmVOR_Transpose( uMt, p->uM, D, p->K);
  2817. cmVOR_PrintL("uMt:\n", p->obj.err.rpt, p->K, p->D, uMt );
  2818. cmPlotLineD(NULL, uMt, uMt+p->K, NULL, p->D, "red", kXPlotPtId );
  2819. }
  2820. if(1)
  2821. {
  2822. cmGmmFree(&p);
  2823. cmReal_t cV0[] = { .7, .3 };
  2824. cmReal_t uM0[] = { .2, .1, .1, .2 };
  2825. cmReal_t sMM0[] = { .01, 0, 0, .01, .01, 0, 0, .01 };
  2826. unsigned flags = 0;
  2827. K = 2;
  2828. D = 2;
  2829. cmGmm_t* p = cmGmmAlloc(c,NULL, K, D, cV0, uM0, sMM0, flags );
  2830. xM[0] = 0.117228;
  2831. xM[1] = 0.110079;
  2832. cmGmmEval(p,xM,1,yV,NULL);
  2833. cmCtxPrint(c,"y: %f\n",yV[0]);
  2834. }
  2835. cmPlotDraw();
  2836. cmGmmFree(&p);
  2837. cmCtxFree(&c);
  2838. }
  2839. //------------------------------------------------------------------------------------------------------------
  2840. cmChmm_t* cmChmmAlloc( cmCtx* c, cmChmm_t* ap, unsigned stateN, unsigned mixN, unsigned dimN, const cmReal_t* iV, const cmReal_t* aM )
  2841. {
  2842. cmChmm_t* p = cmObjAlloc(cmChmm_t,c,ap);
  2843. if( stateN >0 && dimN > 0 )
  2844. if( cmChmmInit(p,stateN,mixN,dimN,iV,aM) != cmOkRC )
  2845. cmChmmFree(&p);
  2846. return p;
  2847. }
  2848. cmRC_t cmChmmFree( cmChmm_t** pp )
  2849. {
  2850. cmRC_t rc = cmOkRC;
  2851. cmChmm_t* p = *pp;
  2852. if( pp == NULL || *pp == NULL )
  2853. return cmOkRC;
  2854. if((rc = cmChmmFinal(p)) != cmOkRC )
  2855. return rc;
  2856. cmMemPtrFree(&p->iV);
  2857. cmMemPtrFree(&p->aM);
  2858. cmMemPtrFree(&p->bV);
  2859. cmMemPtrFree(&p->bM);
  2860. cmObjFree(pp);
  2861. return cmOkRC;
  2862. }
  2863. cmRC_t cmChmmInit( cmChmm_t* p, unsigned stateN, unsigned mixN, unsigned dimN, const cmReal_t* iV, const cmReal_t* aM )
  2864. {
  2865. cmRC_t rc;
  2866. unsigned i;
  2867. if((rc = cmChmmFinal(p)) != cmOkRC )
  2868. return rc;
  2869. // iV[] aM
  2870. /*
  2871. unsigned n = stateN + (stateN*stateN);
  2872. p->iV = cmArrayResizeZ(c, &p->memA, n, cmReal_t );
  2873. p->aM = p->iV + stateN;
  2874. */
  2875. //cmArrayResizeVZ(c,&p->memA, cmReal_t, &p->iV,stateN, &p->aM, stateN*stateN, NULL );
  2876. p->iV = cmMemResizeZ( cmReal_t, p->iV, stateN );
  2877. p->aM = cmMemResizeZ( cmReal_t, p->aM, stateN * stateN );
  2878. p->bV = cmMemResizeZ( cmGmm_t*, p->bV, stateN );
  2879. p->N = stateN;
  2880. p->K = mixN;
  2881. p->D = dimN;
  2882. if( iV != NULL )
  2883. cmVOR_Copy(p->iV,p->N,iV);
  2884. if( aM != NULL )
  2885. cmVOR_Copy(p->aM,p->N*p->N,aM);
  2886. for(i=0; i<p->N; ++i)
  2887. p->bV[i] = cmGmmAlloc( p->obj.ctx, NULL, p->K, p->D, NULL, NULL, NULL, 0 );
  2888. //p->mfp = cmCtxAllocDebugFile( p->obj.ctx,"chmm");
  2889. return cmOkRC;
  2890. }
  2891. cmRC_t cmChmmFinal( cmChmm_t* p )
  2892. {
  2893. if( p != NULL )
  2894. {
  2895. unsigned i;
  2896. for(i=0; i<p->N; ++i)
  2897. cmGmmFree( &p->bV[i] );
  2898. cmMemPtrFree(&p->bM);
  2899. //if( p->mfp != NULL )
  2900. // cmCtxFreeDebugFile(p->obj.ctx,&p->mfp);
  2901. }
  2902. return cmOkRC;
  2903. }
  2904. cmRC_t cmChmmRandomize( cmChmm_t* p, const cmReal_t* oM, unsigned T )
  2905. {
  2906. cmRC_t rc;
  2907. unsigned i;
  2908. unsigned N = p->N;
  2909. // randomize the initial state probabilities
  2910. cmVOR_Random( p->iV, N, 0.0, 1.0 );
  2911. cmVOR_NormalizeProbability( p->iV, N );
  2912. // randomize the state transition matrix
  2913. cmVOR_Random( p->aM, N*N, 0.0, 1.0 );
  2914. for(i=0; i<N; ++i)
  2915. {
  2916. cmVOR_NormalizeProbabilityN( p->aM + i, N, N ); // rows of aM must sum to 1.0
  2917. if((rc = cmGmmRandomize( p->bV[i], oM, T )) != cmOkRC) // randomize the GMM assoc'd with state i
  2918. return rc;
  2919. }
  2920. cmMemPtrFree(&p->bM); // force bM[] to be recalculated
  2921. return cmOkRC;
  2922. }
  2923. cmReal_t _cmChmmKmeansDist( void* userPtr, const cmReal_t* v0, const cmReal_t* v1, unsigned vn )
  2924. { return cmVOR_EuclidDistance(v0,v1,vn); }
  2925. cmRC_t cmChmmSegKMeans( cmChmm_t* p, const cmReal_t* oM, unsigned T, cmReal_t threshProb, unsigned maxIterCnt, unsigned iterCnt )
  2926. {
  2927. cmCtx* c = p->obj.ctx;
  2928. cmRC_t rc = cmOkRC;
  2929. unsigned i,j,k,t;
  2930. unsigned N = p->N;
  2931. unsigned K = p->K;
  2932. unsigned D = p->D;
  2933. //unsigned qV[T];
  2934. //cmReal_t alphaM[N*T];
  2935. //unsigned clusterIdxV[T];
  2936. //cmReal_t centroidM[D*N];
  2937. /*
  2938. unsigned sz = 2*ALIGN_B(T,unsigned) +
  2939. ALIGN_B(N*T,cmReal_t) +
  2940. ALIGN_B(D*N,cmReal_t);
  2941. cmArray mem;
  2942. cmArrayAlloc(c, &mem);
  2943. unsigned* qV = (unsigned*) cmArrayResize(c, &mem, sz, char);
  2944. cmReal_t* alphaM = (cmReal_t*) (qV + ALIGN_T(T, unsigned));
  2945. unsigned* clusterIdxV = (unsigned*) (alphaM + ALIGN_T(N*T,cmReal_t));
  2946. cmReal_t* centroidM = (cmReal_t*) (clusterIdxV + ALIGN_T(T, unsigned));
  2947. */
  2948. unsigned* qV = cmMemAlloc( unsigned, T );
  2949. cmReal_t* alphaM = cmMemAlloc( cmReal_t, N*T);
  2950. unsigned* clusterIdxV = cmMemAlloc( unsigned, T );
  2951. cmReal_t* centroidM = cmMemAlloc( cmReal_t, D*N);
  2952. cmReal_t logPr = 0;
  2953. bool reportFl = true;
  2954. cmChmmRandomize(p,oM,T);
  2955. // cluster the observations into N groups
  2956. cmVOR_Kmeans( qV, centroidM, N, oM, D, T, NULL, 0, false, _cmChmmKmeansDist, NULL );
  2957. for(i=0; i<maxIterCnt; ++i)
  2958. {
  2959. unsigned jnV[N];
  2960. if( reportFl )
  2961. cmCtxPrint(c,"SegKM: ----------------------------------------------------%i\n",i);
  2962. // get the count of data points in each state
  2963. cmVOU_Fill(jnV,N,0);
  2964. for(t=0; t<T; ++t)
  2965. ++jnV[ qV[t] ];
  2966. // for each state
  2967. for(j=0; j<N; ++j)
  2968. {
  2969. cmGmm_t* g = p->bV[j];
  2970. // cluster all datapoints which were assigned to state j
  2971. cmVOR_Kmeans( clusterIdxV, g->uM, K, oM, D, T, qV, j, false, _cmChmmKmeansDist, NULL );
  2972. // for each cluster
  2973. for(k=0; k<K; ++k)
  2974. {
  2975. unsigned kN = 0;
  2976. // kN is count of data points assigned to cluster k
  2977. for(t=0; t<T; ++t)
  2978. if( clusterIdxV[t] == k )
  2979. ++kN;
  2980. g->gV[k] = (cmReal_t)kN/jnV[j];
  2981. // the covar of the kth component is the sample covar of cluster k
  2982. cmVOR_GaussCovariance(g->sMM + (k*D*D), D, oM, T, g->uM + (k*D), clusterIdxV, k );
  2983. }
  2984. if((rc = _cmGmmUpdateCovar(g, g->sMM )) != cmOkRC )
  2985. goto errLabel;
  2986. }
  2987. if( i== 0 )
  2988. {
  2989. // count transitions from i to j
  2990. for(t=0; t<T-1; ++t)
  2991. p->aM[ (qV[t+1]*N) + qV[t] ] += 1.0;
  2992. for(j=0; j<N; ++j)
  2993. {
  2994. // normalize state transitions by dividing by times in each state
  2995. for(k=0; k<N; k++)
  2996. p->aM[ (k*N) + j ] /= jnV[j];
  2997. cmVOR_NormalizeProbabilityN(p->aM + j, N, N);
  2998. cmGmmEval( p->bV[j], oM, 1, p->iV + j, NULL );
  2999. }
  3000. }
  3001. if((rc = cmChmmTrain(p, oM, T, iterCnt,0,0 )) != cmOkRC )
  3002. goto errLabel;
  3003. // calculate the prob. that the new model generated the data
  3004. cmReal_t logPr0 = cmChmmForward(p,oM,T,alphaM,NULL);
  3005. cmReal_t dLogPr = logPr0 - logPr;
  3006. if( reportFl )
  3007. cmCtxPrint(c,"pr:%f d:%f\n",logPr0,dLogPr);
  3008. if( (dLogPr > 0) && (dLogPr < threshProb) )
  3009. break;
  3010. logPr = logPr0;
  3011. // fill qV[] with the state at each time t
  3012. cmChmmDecode(p,oM,T,qV);
  3013. }
  3014. errLabel:
  3015. cmMemPtrFree(&qV);
  3016. cmMemPtrFree(&alphaM);
  3017. cmMemPtrFree(&clusterIdxV);
  3018. cmMemPtrFree(&centroidM);
  3019. return rc;
  3020. }
  3021. cmRC_t cmChmmSetGmm( cmChmm_t* p, unsigned i, const cmReal_t* wV, const cmReal_t* uM, const cmReal_t* sMM, unsigned flags )
  3022. {
  3023. assert( i < p->N);
  3024. cmMemPtrFree(&p->bM); // force bM[] to be recalculated
  3025. return cmGmmInit(p->bV[i],p->K,p->D,wV,uM,sMM,flags);
  3026. }
  3027. // Return the probability of the observation for each state.
  3028. // oV[D] - multi-dim. observation data point
  3029. // pV[N] - probability of this observation for each state
  3030. void cmChmmObsProb( const cmChmm_t* p, const cmReal_t* oV, cmReal_t* prV )
  3031. {
  3032. unsigned i;
  3033. for(i=0; i<p->N; ++i)
  3034. cmGmmEval( p->bV[i], oV, 1, prV + i, NULL );
  3035. }
  3036. // oM[D,T] - observation matrix
  3037. // alphaM[N,T] - prob of being in each state and observtin oM(:,t)
  3038. // bM[N,T] - (optional) state-observation probability matrix
  3039. // logPrV[T] - (optional) record the log prob of the data given the model at each time step
  3040. // Returns sum(logPrV[T])
  3041. cmReal_t cmChmmForward( const cmChmm_t* p, const cmReal_t* oM, unsigned T, cmReal_t* alphaM, cmReal_t* logPrV )
  3042. {
  3043. unsigned t;
  3044. cmReal_t logPr = 0;
  3045. // calc the prob of starting in each state
  3046. if( p->bM == NULL )
  3047. cmChmmObsProb( p, oM, alphaM );
  3048. else
  3049. cmVOR_Copy( alphaM, p->N*T, p->bM );
  3050. cmVOR_MultVV( alphaM, p->N, p->iV );
  3051. cmReal_t s = cmVOR_Sum(alphaM,p->N);
  3052. cmVOR_DivVS(alphaM,p->N,s);
  3053. //cmVOR_PrintL("alpha:\n",p->obj.err.rpt,p->N,1,alphaM);
  3054. for(t=1; t<T; ++t)
  3055. {
  3056. cmReal_t tmp[p->N];
  3057. cmReal_t* alphaV = alphaM + t*p->N;
  3058. // calc the prob of the observation for each state
  3059. if( p->bM == NULL )
  3060. cmChmmObsProb(p,oM + (t*p->D), alphaV );
  3061. // calc. the prob. of transitioning to each state at time t, from each state at t-1
  3062. cmVOR_MultVVM(tmp,p->N, alphaM + ((t-1)*p->N), p->N, p->aM );
  3063. // calc the joint prob of transitioning from each state to each state and observing O(t).
  3064. cmVOR_MultVV(alphaV, p->N, tmp );
  3065. // scale the probabilities to prevent underflow
  3066. s = cmVOR_Sum(alphaV,p->N);
  3067. cmVOR_DivVS(alphaV,p->N,s);
  3068. // track the log prob. of the model having generated the data up to time t.
  3069. cmReal_t pr = log(s);
  3070. if( logPrV != NULL )
  3071. logPrV[t] = pr;
  3072. logPr += pr;
  3073. }
  3074. return logPr;
  3075. }
  3076. // oM[D,T]
  3077. // betaM[N,T]
  3078. void cmChmmBackward( const cmChmm_t* p, const cmReal_t* oM, unsigned T, cmReal_t* betaM )
  3079. {
  3080. cmVOR_Fill(betaM,p->N*T,1.0);
  3081. assert(T >= 2 );
  3082. int t = (int)T - 2;
  3083. for(; t>=0; --t)
  3084. {
  3085. cmReal_t tmp[p->N];
  3086. if( p->bM == NULL )
  3087. cmChmmObsProb(p,oM+((t+1)*p->D), tmp );
  3088. else
  3089. cmVOR_Copy(tmp,p->N,p->bM + ((t+1)*p->N));
  3090. cmVOR_MultVV(tmp,p->N,betaM + ((t+1)*p->N));
  3091. cmVOR_MultVMV(betaM+(t*p->N),p->N, p->aM, p->N, tmp );
  3092. cmVOR_NormalizeProbability(betaM+(t*p->N),p->N );
  3093. }
  3094. }
  3095. cmReal_t cmChmmCompare( const cmChmm_t* p0, const cmChmm_t* p1, unsigned T )
  3096. {
  3097. assert(p0->D == p1->D);
  3098. assert(p0->N == p1->N);
  3099. cmReal_t oM[p0->D*T];
  3100. cmReal_t alphaM[p0->N*T];
  3101. cmChmmGenerate(p0,oM,T,NULL);
  3102. cmReal_t logPr00 = cmChmmForward(p0,oM,T,alphaM,NULL);
  3103. cmReal_t logPr01 = cmChmmForward(p1,oM,T,alphaM,NULL);
  3104. cmChmmGenerate(p1,oM,T,NULL);
  3105. cmReal_t logPr10 = cmChmmForward(p0,oM,T,alphaM,NULL);
  3106. cmReal_t logPr11 = cmChmmForward(p1,oM,T,alphaM,NULL);
  3107. cmReal_t d0 = (logPr01-logPr00)/T;
  3108. cmReal_t d1 = (logPr10-logPr11)/T;
  3109. return (d0+d1)/2;
  3110. }
  3111. cmRC_t cmChmmGenerate( const cmChmm_t* p, cmReal_t* oM, unsigned T, unsigned* sV )
  3112. {
  3113. unsigned i,si;
  3114. // use weighted random selection to choose an intitial state
  3115. cmVOR_WeightedRandInt(&si, 1, p->iV, p->N );
  3116. for(i=0; i<T; ++i)
  3117. {
  3118. if( sV != NULL )
  3119. sV[i] = si;
  3120. // generate a random value using the GMM assoc'd with the current state
  3121. cmGmmGenerate( p->bV[si], oM + (i*p->D), 1 );
  3122. // choose the next state using the transition weights from the current state
  3123. cmVOR_WeightedRandInt(&si, 1, p->aM + (si*p->N), p->N );
  3124. }
  3125. return cmOkRC;
  3126. }
  3127. cmRC_t cmChmmDecode( cmChmm_t* p, const cmReal_t* oM, unsigned T, unsigned* yV )
  3128. {
  3129. int i,j,t;
  3130. unsigned N = p->N;
  3131. //unsigned psiM[N*T];
  3132. //cmReal_t delta[N];
  3133. /*
  3134. unsigned sz = ALIGN_B(N*T,unsigned) + ALIGN_B(N,cmReal_t);
  3135. cmArray mem;
  3136. cmArrayAlloc(c, &mem);
  3137. unsigned* psiM = (unsigned*) cmArrayResize(c, &mem, sz, char);
  3138. cmReal_t* delta = (cmReal_t*) (psiM + ALIGN_T(N*T,unsigned));
  3139. */
  3140. unsigned* psiM = cmMemAlloc( unsigned, N*T );
  3141. cmReal_t* delta= cmMemAlloc( cmReal_t, N );
  3142. // get the prob of starting in each state
  3143. if( p->bM == NULL )
  3144. cmChmmObsProb( p, oM, delta );
  3145. else
  3146. cmVOR_Copy( delta, N, p->bM );
  3147. cmVOR_MultVV( delta, p->N, p->iV );
  3148. cmVOR_NormalizeProbability(delta, p->N);
  3149. for(t=1; t<T; ++t)
  3150. {
  3151. cmReal_t mV[N];
  3152. const cmReal_t* ap = p->aM;
  3153. // calc. the most likely new state given the most likely prev state
  3154. // and the transition matrix
  3155. for(i=0; i<N; ++i)
  3156. {
  3157. const cmReal_t* dp = delta;
  3158. unsigned psiIdx = t*N + i;
  3159. mV[i] = *ap++ * *dp++;
  3160. psiM[ psiIdx ] = 0;
  3161. // find max value of: delta .* A(:,i)
  3162. for(j=1; j<N; ++j )
  3163. {
  3164. cmReal_t v = *ap++ * *dp++;
  3165. if( v > mV[i] )
  3166. {
  3167. mV[i] = v;
  3168. psiM[ psiIdx ] = j;
  3169. }
  3170. }
  3171. }
  3172. // mV[] now holds the prob. of the max likelihood state at time t
  3173. // for each possible state at t-1
  3174. // psiM[:,t] holds the index of the max likelihood state
  3175. // condition the most likely new state on the observations
  3176. if( p->bM == NULL )
  3177. cmChmmObsProb(p,oM + (t*p->D), delta);
  3178. else
  3179. cmVOR_Copy(delta, N, p->bM + (t*p->N) );
  3180. cmVOR_MultVV(delta, N, mV ); // condition it on the max. like current states
  3181. cmVOR_NormalizeProbability( delta, N ); // normalize the prob.
  3182. }
  3183. // unwind psiM[] to form the max. likelihood state sequence
  3184. yV[T-1] = cmVOR_MaxIndex(delta,N,1);
  3185. for(t=T-2; t>=0; --t)
  3186. yV[t] = psiM[ ((t+1)*N) + yV[t+1] ];
  3187. cmMemPtrFree(&psiM);
  3188. cmMemPtrFree(&delta);
  3189. return cmOkRC;
  3190. }
  3191. cmRC_t cmChmmTrain( cmChmm_t* p, const cmReal_t* oM, unsigned T, unsigned iterCnt, cmReal_t thresh, unsigned flags )
  3192. {
  3193. cmRC_t rc = cmOkRC;
  3194. unsigned i,j,k,t,d;
  3195. unsigned iter;
  3196. unsigned N = p->N;
  3197. unsigned K = p->K;
  3198. unsigned D = p->D;
  3199. unsigned De2 = D * D;
  3200. bool mixFl = !cmIsFlag(flags,kNoTrainMixCoeffChmmFl);
  3201. bool meanFl = !cmIsFlag(flags,kNoTrainMeanChmmFl);
  3202. bool covarFl = !cmIsFlag(flags,kNoTrainCovarChmmFl);
  3203. bool bFl = mixFl | meanFl | covarFl;
  3204. bool calcBFl = true;
  3205. bool progFl = false;
  3206. bool timeProgFl = false;
  3207. cmReal_t progInc = 0.1;
  3208. cmReal_t progFrac = 0;
  3209. cmReal_t logProb = 0;
  3210. //cmReal_t alphaM[N*T]; // alpha[N,T]
  3211. //cmReal_t betaM[N*T]; // betaM[N,T]
  3212. //cmReal_t logPrV[T];
  3213. //cmReal_t EpsM[N*N];
  3214. //cmReal_t BK[N*K*T];
  3215. //cmReal_t gamma_jk[N*K];
  3216. //cmReal_t uM[K*D*N];
  3217. //cmReal_t sMM[K*De2*N];
  3218. /*
  3219. unsigned sz = ALIGN_T(N*T, cmReal_t) +
  3220. ALIGN_T(N*T, cmReal_t) +
  3221. ALIGN_T(T, cmReal_t) +
  3222. ALIGN_T(N*N, cmReal_t) +
  3223. ALIGN_T(N*K*T, cmReal_t) +
  3224. ALIGN_T(N*K, cmReal_t) +
  3225. ALIGN_T(K*D*N, cmReal_t) +
  3226. ALIGN_T(K*De2*N,cmReal_t);
  3227. cmArray mem;
  3228. cmArrayAlloc(c, &mem);
  3229. cmReal_t* alphaM = cmArrayResize(c, &mem, sz, cmReal_t); // alpha[N,T]
  3230. cmReal_t* betaM = alphaM + ALIGN_T(N*T, cmReal_t); // betaM[N,T]
  3231. cmReal_t* logPrV = betaM + ALIGN_T(N*T, cmReal_t);
  3232. cmReal_t* EpsM = logPrV + ALIGN_T(T, cmReal_t);
  3233. cmReal_t* BK = EpsM + ALIGN_T(N*N, cmReal_t);
  3234. cmReal_t* gamma_jk = BK + ALIGN_T(N*K*T,cmReal_t);
  3235. cmReal_t* uM = gamma_jk + ALIGN_T(N*K, cmReal_t);
  3236. cmReal_t* sMM = uM + ALIGN_T(K*D*N,cmReal_t);
  3237. */
  3238. cmReal_t* alphaM = cmMemAlloc( cmReal_t, N*T );
  3239. cmReal_t* betaM = cmMemAlloc( cmReal_t, N*T );
  3240. cmReal_t* logPrV = cmMemAlloc( cmReal_t, T );
  3241. cmReal_t* EpsM = cmMemAlloc( cmReal_t, N*N );
  3242. cmReal_t* BK = cmMemAlloc( cmReal_t, N*K*T );
  3243. cmReal_t* gamma_jk = cmMemAlloc( cmReal_t, N*K );
  3244. cmReal_t* uM = cmMemAlloc( cmReal_t, K*D*N );
  3245. cmReal_t* sMM = cmMemAlloc( cmReal_t, K*De2*N );
  3246. if( thresh <=0 )
  3247. thresh = 0.0001;
  3248. //cmArrayResizeZ(c,&p->memC,N*T,cmReal_t);
  3249. p->bM = cmMemResizeZ( cmReal_t, p->bM, N*T);
  3250. for(iter=0; iter<iterCnt; ++iter)
  3251. {
  3252. // zero the mean and covar summation arrays
  3253. cmVOR_Fill(uM, K*D *N,0);
  3254. cmVOR_Fill(sMM, K*De2*N,0);
  3255. cmVOR_Fill(EpsM,N*N, 0);
  3256. cmVOR_Fill(gamma_jk,N*K,0);
  3257. //
  3258. // B[i,t] The prob that state i generated oM(:,t)
  3259. // BK[i,k,t] The prob that state i component k generated oM(:,t)
  3260. // Note: B[i,t] = sum(BK(i,k,:))
  3261. //
  3262. if( calcBFl || bFl )
  3263. {
  3264. calcBFl = false;
  3265. for(t=0; t<T; ++t)
  3266. {
  3267. // prob. that state i generated objservation O[t]
  3268. for(i=0; i<N; ++i )
  3269. cmGmmEval( p->bV[i], oM + (t*D), 1, p->bM + (t*N) + i, BK + (t*N*K) + (i*K) );
  3270. }
  3271. }
  3272. // alpha[N,T] is prob. of transitioning forward to each state given the observed data
  3273. cmReal_t logProb0 = cmChmmForward( p, oM, T, alphaM, logPrV );
  3274. // check for convergence
  3275. cmReal_t dLogProb = fabs(logProb0-logProb) / ((fabs(logProb0)+fabs(logProb)+cmReal_EPSILON)/2);
  3276. if( dLogProb < thresh )
  3277. break;
  3278. logProb = logProb0;
  3279. // betaM[N,T] is prob of transitioning backward from each state given the observed data
  3280. cmChmmBackward(p, oM, T, betaM );
  3281. if(progFl)
  3282. cmCtxPrint(p->obj.ctx,"%i (%f) ",iter+1, dLogProb );
  3283. if(timeProgFl)
  3284. progFrac = progInc;
  3285. // for each time step
  3286. for(t=0; t<T-1; ++t)
  3287. {
  3288. // oV[D] is the observation at step t
  3289. const cmReal_t* oV = oM + (t*D);
  3290. //
  3291. // Update EpsM[N,N] (6.37)
  3292. // (prob. of being in state i at time t and transitioning
  3293. // to state j at time t+1)
  3294. //
  3295. cmReal_t E[N*N];
  3296. // for each possible state transition
  3297. for(i=0; i<N; ++i)
  3298. for(j=0; j<N; ++j)
  3299. {
  3300. E[ i + (j*N) ]
  3301. = exp(log(alphaM[ (t*N) + i ])
  3302. + log(p->aM[ i + (j*N) ])
  3303. + log(p->bM[ ((t+1)*N) + j ])
  3304. + log(betaM[ ((t+1)*N) + j ]));
  3305. }
  3306. cmVOR_NormalizeProbability( E, N*N );
  3307. cmVOR_AddVV( EpsM, N*N, E );
  3308. // If t==0 then update the initial state prob's
  3309. if( t == 0 )
  3310. {
  3311. for(i=0; i<N; ++i)
  3312. p->iV[i] = cmVOR_SumN(EpsM+i, N, N);
  3313. assert( cmVOR_IsNormal(p->iV,N) );
  3314. }
  3315. if( bFl )
  3316. {
  3317. //
  3318. // Calculate gamma_jk[]
  3319. //
  3320. cmReal_t gtjk[N*K]; // gamma_jk[N,K] at time t
  3321. cmReal_t abV[N]; //
  3322. // (alphaM[j,t] * betaM[j:t]) / (sum(alphaM[:,t] * betaM[:,t]))
  3323. cmVOR_MultVVV(abV,N,alphaM + t*N, betaM+t*N);
  3324. cmReal_t abSum = cmVOR_Sum(abV,N);
  3325. if( abSum<=0 )
  3326. assert(abSum>0);
  3327. cmVOR_DivVS(abV,N,abSum);
  3328. for(j=0; j<N; ++j)
  3329. {
  3330. cmReal_t bkSum = cmVOR_Sum(BK + (t*N*K) + (j*K), K );
  3331. for(k=0; k<K; ++k)
  3332. gtjk[ (k*N)+j ] = abV[j] * (BK[ (t*N*K) + (j*K) + k ] / bkSum);
  3333. }
  3334. // sum gtjk[N,K] into gamma_jk (integrate gamma over time)
  3335. cmVOR_AddVV( gamma_jk, N*K, gtjk );
  3336. // update the mean and covar numerators
  3337. for(j=0; j<N; ++j)
  3338. {
  3339. cmReal_t* uV = uM + (j*D*K);
  3340. cmReal_t* sV = sMM + (j*De2*K);
  3341. for(k=0; k<K; ++k,uV+=D,sV+=De2)
  3342. {
  3343. cmReal_t c = gtjk[ (k*N)+j ];
  3344. if( covarFl )
  3345. {
  3346. cmReal_t dV[D];
  3347. cmReal_t dM[D*D];
  3348. // covar numerator b[j].sM[k]
  3349. cmVOR_SubVVV(dV, D, oV, p->bV[j]->uM + (k*D));
  3350. cmVOR_MultMMM( dM, D, D, dV, dV, 1 );
  3351. cmVOR_MultVS( dM, De2, c );
  3352. cmVOR_AddVV( sV, De2, dM );
  3353. }
  3354. if( meanFl )
  3355. {
  3356. // mean numerator b[j].uM[k]
  3357. for(d=0; d<D; ++d)
  3358. uV[d] += c * oV[ d ];
  3359. }
  3360. }
  3361. }
  3362. }
  3363. if( timeProgFl && (t >= floor(T*progFrac)) )
  3364. {
  3365. cmCtxPrint(p->obj.ctx,"%i ", (unsigned)round(progFrac*100) );
  3366. progFrac+=progInc;
  3367. }
  3368. } // end time loop
  3369. for(i=0; i<N; ++i)
  3370. {
  3371. // update the state transition matrix
  3372. cmReal_t den = cmVOR_SumN(EpsM + i, N, N );
  3373. assert(den != 0 );
  3374. for(j=0; j<N; ++j)
  3375. p->aM[ i + (j*N) ] = EpsM[ i + (j*N) ] / den;
  3376. if( bFl )
  3377. {
  3378. // update the mean, covariance and mix coefficient
  3379. cmGmm_t* g = p->bV[i];
  3380. const cmReal_t* uV = uM + (i*D*K);
  3381. const cmReal_t* sMV = sMM + (i*De2*K);
  3382. for(k=0; k<K; ++k,uV+=D,sMV+=De2)
  3383. {
  3384. cmReal_t gjk = gamma_jk[ (k*N) + i ];
  3385. if( meanFl )
  3386. cmVOR_DivVVS(g->uM + (k*D), D, uV, gjk );
  3387. if( covarFl )
  3388. cmVOR_DivVVS(g->sMM + (k*De2), De2, sMV, gjk );
  3389. if( mixFl )
  3390. g->gV[k] = gjk / cmVOR_SumN( gamma_jk + i, K, N );
  3391. }
  3392. if((rc = _cmGmmUpdateCovar(g,g->sMM)) != cmOkRC )
  3393. goto errLabel;
  3394. }
  3395. }
  3396. assert( cmVOR_IsNormalZ(p->aM,N*N) );
  3397. if( timeProgFl )
  3398. cmCtxPrint(p->obj.ctx,"\n");
  3399. } // end iter loop
  3400. if( progFl)
  3401. cmCtxPrint(p->obj.ctx,"\n");
  3402. if( p->mfp != NULL )
  3403. {
  3404. // first line is iV[N]
  3405. cmMtxFileRealExec(p->mfp,p->iV,p->N);
  3406. // next N lines are aM[N,N]
  3407. for(i=0; i<p->N; ++i)
  3408. cmMtxFileRealExecN(p->mfp,p->aM + i,p->N,p->N);
  3409. // next T lines are bM[T,N]
  3410. if( p->bM != NULL )
  3411. for(i=0; i<T; ++i)
  3412. cmMtxFileRealExec(p->mfp, p->bM + (i*p->N),p->N);
  3413. }
  3414. errLabel:
  3415. cmMemPtrFree(&alphaM);
  3416. cmMemPtrFree(&betaM);
  3417. cmMemPtrFree(&logPrV);
  3418. cmMemPtrFree(&EpsM);
  3419. cmMemPtrFree(&BK);
  3420. cmMemPtrFree(&gamma_jk);
  3421. cmMemPtrFree(&uM);
  3422. cmMemPtrFree(&sMM);
  3423. return rc;
  3424. }
  3425. void cmChmmPrint( cmChmm_t* p )
  3426. {
  3427. unsigned i;
  3428. cmCtxPrint(p->obj.ctx,"======================================== \n");
  3429. cmVOR_PrintL("iV: ", p->obj.err.rpt, 1, p->N, p->iV);
  3430. cmVOR_PrintL("aM:\n", p->obj.err.rpt, p->N, p->N, p->aM);
  3431. for(i=0; i<p->N; ++i)
  3432. {
  3433. cmCtxPrint(p->obj.ctx,"bV[%i] ----------------- %i \n",i,i);
  3434. cmGmmPrint(p->bV[i],false);
  3435. }
  3436. }
  3437. void cmChmmTestForward( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  3438. {
  3439. cmReal_t oM[] = {
  3440. 0.117228, 0.110079,
  3441. 0.154646, 0.210436,
  3442. 0.947468, 0.558136,
  3443. 0.202023, 0.138123,
  3444. 0.929933, 0.456102,
  3445. 0.897566, 0.685078,
  3446. 0.945177, 0.663145,
  3447. 0.272399, 0.055107,
  3448. 0.863386, 0.621546,
  3449. 0.217545, 0.274709,
  3450. 0.838777, 0.650038,
  3451. 0.134966, 0.159472,
  3452. 0.053990, 0.264051,
  3453. 0.884269, 0.550019,
  3454. 0.764787, 0.554484,
  3455. 0.114771, 0.077518,
  3456. 0.835121, 0.606137,
  3457. 0.070733, 0.120015,
  3458. 0.819814, 0.588482,
  3459. 0.105511, 0.197699,
  3460. 0.824778, 0.533047,
  3461. 0.945223, 0.511411,
  3462. 0.126971, 0.050083,
  3463. 0.869497, 0.567737,
  3464. 0.144866, 0.197363,
  3465. 0.985726, 0.590402,
  3466. 0.181094, 0.192827,
  3467. 0.162179, 0.155297,
  3468. 1.034691, 0.513413,
  3469. 0.220708, 0.036158,
  3470. 0.750061, 0.671224,
  3471. 0.246971, 0.093246,
  3472. 0.997567, 0.680491,
  3473. 0.916887, 0.530981,
  3474. 0.022328, 0.121969,
  3475. 0.794031, 0.618081,
  3476. 0.845066, 0.625512,
  3477. 0.174731, 0.094773,
  3478. 0.968665, 0.652435,
  3479. 0.932484, 0.388081,
  3480. 0.202732, 0.148710,
  3481. 0.911307, 0.637139,
  3482. 0.211127, 0.201362,
  3483. 0.138152, 0.057290,
  3484. 0.819132, 0.579888,
  3485. 0.135625, 0.176140,
  3486. 0.146017, 0.157853,
  3487. 0.950319, 0.624150,
  3488. 0.285064, 0.038825,
  3489. 0.716844, 0.575189,
  3490. 0.907433, 0.504946,
  3491. 0.219772, 0.129993,
  3492. 0.076507, 0.193079,
  3493. 0.808906, 0.548409,
  3494. 0.880892, 0.523950,
  3495. 0.758099, 0.636729,
  3496. 1.014017, 0.557120,
  3497. 0.277888, 0.181492,
  3498. 0.877588, 0.508634,
  3499. 0.251266, 0.225890,
  3500. 0.990904, 0.482949,
  3501. 0.999899, 0.534579,
  3502. 0.904179, 0.707349,
  3503. 0.952879, 0.617955,
  3504. 0.172068, 0.151984,
  3505. 1.026262, 0.662600,
  3506. 0.812003, 0.430856,
  3507. 0.173393, 0.017885,
  3508. 0.099370, 0.146661,
  3509. 0.785785, 0.564333,
  3510. 0.698222, 0.449299,
  3511. 0.276539, 0.225314,
  3512. 0.799271, 0.618159,
  3513. 0.098813, 0.090839,
  3514. 0.883666, 0.554150,
  3515. 0.274934, 0.185403,
  3516. 0.200419, 0.109972,
  3517. 0.925076, 0.608610,
  3518. 0.864486, 0.348689,
  3519. 0.176733, 0.136235,
  3520. 0.967278, 0.656875,
  3521. 0.986994, 0.659877,
  3522. 1.015618, 0.596549,
  3523. 0.689903, 0.528107,
  3524. 0.978238, 0.630989,
  3525. 0.269847, 0.144358,
  3526. 0.092303, 0.139894,
  3527. 0.168185, 0.095327,
  3528. 0.897767, 0.584203,
  3529. 0.068316, 0.018452,
  3530. 0.953395, 0.530545,
  3531. 0.266405, 0.173987,
  3532. 0.233845, 0.205276,
  3533. 0.900060, 0.477108,
  3534. 0.052909, 0.053077,
  3535. 0.885850, 0.496546,
  3536. 0.268494, 0.104785,
  3537. 1.041405, 0.655079,
  3538. 1.055915, 0.697988,
  3539. 0.181569, 0.146840
  3540. };
  3541. unsigned i;
  3542. cmReal_t iV[] = { .5 , .5};
  3543. cmReal_t A[] = { .3, .6, .7, .4 };
  3544. cmReal_t cV0[] = { .7, .3 };
  3545. cmReal_t uM0[] = { .2, .1, .1, .2 };
  3546. cmReal_t sMM0[]= { .01, 0, 0, .01, .01, 0, 0, .01 };
  3547. cmReal_t cV1[] = { .2, .8 };
  3548. cmReal_t uM1[] = { .8, .9, .9, .5 };
  3549. cmReal_t sMM1[]= { .01, 0, 0, .01, .01, 0, 0, .01 };
  3550. unsigned T = 100;
  3551. unsigned N = 2;
  3552. unsigned K = 2;
  3553. unsigned D = 2;
  3554. cmReal_t alphaM[N*T];
  3555. cmReal_t betaM[N*T];
  3556. cmReal_t logPrV[T];
  3557. unsigned qV[T];
  3558. unsigned sV[T];
  3559. cmReal_t oMt[T*D];
  3560. // scale covariance
  3561. cmVOR_MultVS(sMM0,D*D*K,1);
  3562. cmVOR_MultVS(sMM1,D*D*K,1);
  3563. cmCtx c;
  3564. cmCtxAlloc(&c,rpt,lhH,stH);
  3565. cmChmm_t* p = cmChmmAlloc(&c,NULL,N,K,D,iV,A);
  3566. cmChmmSetGmm(p,0,cV0,uM0,sMM0,0);
  3567. cmChmmSetGmm(p,1,cV1,uM1,sMM1,0);
  3568. cmChmmPrint(p);
  3569. cmChmmGenerate(p, oM, T, sV );
  3570. cmChmmForward( p, oM, T, alphaM,logPrV );
  3571. //cmVOR_PrintL("logPrV:\n",rpt,1,T,logPrV);
  3572. cmCtxPrint(&c,"log prob:%f\n", cmVOR_Sum(logPrV,T));
  3573. cmChmmBackward( p, oM, T, betaM );
  3574. //cmVOR_PrintL("beta:\n",rpt,N,T,betaM);
  3575. cmChmmDecode(p,oM,T,qV);
  3576. cmVOU_PrintL("sV:\n",rpt,1,T,sV);
  3577. cmVOU_PrintL("qV:\n",rpt,1,T,qV);
  3578. unsigned d=0;
  3579. for(i=0; i<T; ++i)
  3580. d += sV[i] != qV[i];
  3581. cmCtxPrint(&c,"Diff:%i\n",d);
  3582. cmPlotSetup("Chmm Forward Test",1,1);
  3583. cmVOR_Transpose(oMt,oM,D,T);
  3584. cmPlotLineD(NULL, oMt, oMt+T, NULL, T, "blue", kXPlotPtId );
  3585. cmPlotDraw();
  3586. cmChmmFree(&p);
  3587. }
  3588. void cmChmmTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  3589. {
  3590. time_t t = time(NULL); //0x4b9e82aa; //time(NULL);
  3591. srand( t );
  3592. printf("TIME: 0x%x\n",(unsigned)t);
  3593. //cmChmmTestForward(vReportFunc);
  3594. //return;
  3595. unsigned i;
  3596. cmReal_t iV[] = { 1.0/3.0, 1.0/3.0, 1.0/3.0 };
  3597. cmReal_t A[] = { .1, .4, .7, .4, .2, .2 };
  3598. cmReal_t cV0[] = { .7, .3 };
  3599. cmReal_t uM0[] = { .2, .1, .1, .2 };
  3600. cmReal_t sMM0[] = { .01, 0, 0, .01, .01, 0, 0, .01 };
  3601. cmReal_t cV1[] = { .2, .8 };
  3602. cmReal_t uM1[] = { .8, .9, .9, .8 };
  3603. cmReal_t sMM1[] = { .01, 0, 0, .01, .01, 0, 0, .01 };
  3604. cmReal_t cV2[] = { .5, .5 };
  3605. cmReal_t uM2[] = { .5, .5, .5, .5 };
  3606. cmReal_t sMM2[] = { .01, 0, 0, .01, .01, 0, 0, .01 };
  3607. cmReal_t kmThreshProb = 0.001;
  3608. unsigned kmMaxIterCnt = 10;
  3609. unsigned iterCnt = 20;
  3610. unsigned N = sizeof(iV) / sizeof(iV[0]);
  3611. unsigned K = sizeof(cV0) / sizeof(cV0[0]);
  3612. unsigned D = sizeof(uM0) / sizeof(uM0[0]) / K;
  3613. unsigned T = 100;
  3614. cmReal_t alphaM[N*T];
  3615. cmReal_t oM[D*T];
  3616. unsigned sV[T];
  3617. unsigned qV[T];
  3618. cmCtx c;
  3619. cmCtxAlloc(&c,rpt,lhH,stH);
  3620. cmCtxPrint(&c,"N:%i K:%i D:%i\n",N,K,D);
  3621. cmChmm_t* p = cmChmmAlloc(&c,NULL,N,K,D,iV,A);
  3622. cmChmmSetGmm(p,0,cV0,uM0,sMM0,0);
  3623. cmChmmSetGmm(p,1,cV1,uM1,sMM1,0);
  3624. cmChmmSetGmm(p,2,cV2,uM2,sMM2,0);
  3625. // generate data using the parameters above
  3626. cmChmmGenerate(p,oM,T,sV);
  3627. cmVOU_PrintL("sV: ",rpt,1,T,sV);
  3628. cmChmmRandomize(p,oM,T);
  3629. if(cmChmmSegKMeans(p,oM,T,kmThreshProb,kmMaxIterCnt,iterCnt) != cmOkRC )
  3630. goto errLabel;
  3631. if( cmChmmTrain(p,oM,T,iterCnt,0,0) != cmOkRC )
  3632. goto errLabel;
  3633. //cmChmmPrint(p);
  3634. cmChmmDecode(p,oM,T,qV);
  3635. cmReal_t pr = cmChmmForward(p,oM,T,alphaM,NULL);
  3636. cmCtxPrint(&c,"pr:%f\n",pr);
  3637. cmVOU_PrintL("sV:\n",rpt,1,T,sV);
  3638. cmVOU_PrintL("qV:\n",rpt,1,T,qV);
  3639. unsigned d=0;
  3640. for(i=0; i<T; ++i)
  3641. d += sV[i] != qV[i];
  3642. cmCtxPrint(&c,"Diff:%i\n",d);
  3643. errLabel:
  3644. cmChmmFree(&p);
  3645. }
  3646. //------------------------------------------------------------------------------------------------------------
  3647. cmChord* cmChordAlloc( cmCtx* c, cmChord* ap, const cmReal_t* chromaM, unsigned T )
  3648. {
  3649. unsigned i,j;
  3650. unsigned S = 6;
  3651. unsigned N = 24;
  3652. unsigned D = 12;
  3653. cmChord* p = cmObjAlloc(cmChord,c,ap);
  3654. p->h = cmChmmAlloc( p->obj.ctx, NULL, 0, 0, 0, NULL, NULL );
  3655. if( chromaM != NULL && T > 0 )
  3656. if( cmChordInit(p,chromaM,T) != cmOkRC )
  3657. cmChordFree(&p);
  3658. p->N = N;
  3659. p->D = D;
  3660. p->S = kTonalSpaceDimCnt;
  3661. /*
  3662. // iv[N] aM[N*N] uM[D*N] sMM[D*D*N] phiM[D*S] tsxxxV[S]
  3663. unsigned n = ALIGN_T(N, cmReal_t) +
  3664. ALIGN_T(N*N, cmReal_t) +
  3665. ALIGN_T(D*N, cmReal_t) +
  3666. ALIGN_T(D*D*N,cmReal_t) +
  3667. ALIGN_T(D*S, cmReal_t) +
  3668. 2*ALIGN_T(S, cmReal_t);
  3669. p->iV = cmArrayResizeZ(c, &p->memA, n, cmReal_t);
  3670. p->aM = p->iV + ALIGN_T(N, cmReal_t);
  3671. p->uM = p->aM + ALIGN_T(N*N, cmReal_t);
  3672. p->sMM = p->uM + ALIGN_T(D*N, cmReal_t);
  3673. p->phiM = p->sMM + ALIGN_T(D*D*N,cmReal_t);
  3674. p->tsMeanV = p->phiM + ALIGN_T(D*S, cmReal_t);
  3675. p->tsVarV = p->tsMeanV + ALIGN_T(S, cmReal_t);
  3676. */
  3677. p->iV = cmMemAllocZ( cmReal_t, N );
  3678. p->aM = cmMemAllocZ( cmReal_t, N*N);
  3679. p->uM = cmMemAllocZ( cmReal_t, D*N);
  3680. p->sMM = cmMemAllocZ( cmReal_t, D*D*N );
  3681. p->phiM = cmMemAllocZ( cmReal_t, D*S);
  3682. p->tsMeanV = cmMemAllocZ( cmReal_t, S );
  3683. p->tsVarV = cmMemAllocZ( cmReal_t, S );
  3684. // initialize iV[N] (HMM initial state probabilities)
  3685. cmVOR_Fill(p->iV,N,1.0/N);
  3686. // initialize aM[N,N] (HMM transition matrix)
  3687. cmReal_t epsilon = 0.01;
  3688. cmReal_t CMaj2any[] = { 12, 2, 8, 6, 4, 10, 0, 10, 4, 6, 8, 2, 5, 5, 9, 1, 11, 3, 7, 7, 3, 11, 1, 9 };
  3689. for(i=0; i<N; ++i)
  3690. {
  3691. cmVOR_Copy( p->aM+(i*N), N, CMaj2any );
  3692. cmVOR_Rotate( CMaj2any, N, 1 );
  3693. }
  3694. cmVOR_AddVS(p->aM, N*N, epsilon);
  3695. cmVOR_DivVS(p->aM, N*N, ( (N/2)*(N/2) ) + (N*epsilon) );
  3696. //cmVOR_PrintL("A:\n",p->obj.err.rpt,N,N,A);
  3697. // initialize sMM[D*D,N] (HMM covariance matrices)
  3698. cmReal_t diagMV[] = { 1, 0.2, 0.2, 0.2, 1.0, 0.2, 0.2, 1.0, 0.2, 0.2, 0.2, 0.2 };
  3699. cmReal_t diagmV[] = { 1, 0.2, 0.2, 1.0, 0.2, 0.2, 0.2, 1.0, 0.2, 0.2, 0.2, 0.2 };
  3700. cmReal_t Maj[D*D];
  3701. cmReal_t Min[D*D];
  3702. cmVOR_DiagZ(Maj,D,diagMV);
  3703. Maj[ (4*D) + 0 ] = 0.6; Maj[ (0*D) + 4 ] = 0.6;
  3704. Maj[ (7*D) + 0 ] = 0.8; Maj[ (0*D) + 7 ] = 0.8;
  3705. Maj[ (7*D) + 4 ] = 0.8; Maj[ (4*D) + 7 ] = 0.8;
  3706. cmVOR_DiagZ(Min,D,diagmV);
  3707. Min[ (3*D) + 0 ] = 0.6; Min[ (0*D) + 3 ] = 0.6;
  3708. Min[ (7*D) + 0 ] = 0.8; Min[ (0*D) + 7 ] = 0.8;
  3709. Min[ (7*D) + 3 ] = 0.8; Min[ (3*D) + 7 ] = 0.8;
  3710. cmReal_t* sM = p->sMM;
  3711. for(i=0; i<N/2; ++i,sM+=D*D)
  3712. cmVOR_RotateM( sM, D, D, Maj, i, i );
  3713. for(i=0; i<N/2; ++i,sM+=D*D)
  3714. cmVOR_RotateM( sM, D, D, Min, i, i );
  3715. /*
  3716. cmVOR_PrintL("Maj:\n",p->obj.err.rpt,D,D,Maj);
  3717. cmVOR_PrintL("Min:\n",p->obj.err.rpt,D,D,Min);
  3718. for(i=0; i<N; ++i)
  3719. {
  3720. cmCtxPrint(c,"%i----\n",i);
  3721. cmVOR_PrintL("sM:\n",p->obj.err.rpt,D,D,sMM + (i*D*D));
  3722. }
  3723. */
  3724. // initialize uM[D,N] (HMM GMM mean vectors)
  3725. cmVOR_Fill(p->uM,D*N,0);
  3726. for(i=0; i<D; ++i)
  3727. {
  3728. unsigned dom = (i+7) % D;
  3729. unsigned medM = (i+4) % D;
  3730. unsigned medm = (i+3) % D;
  3731. p->uM[ (i * D) + i ] = 1;
  3732. p->uM[ (i * D) + medM ] = 1;
  3733. p->uM[ (i * D) + dom ] = 1;
  3734. p->uM[ ((i+D) * D) + i ] = 1;
  3735. p->uM[ ((i+D) * D) + medm ] = 1;
  3736. p->uM[ ((i+D) * D) + dom ] = 1;
  3737. }
  3738. cmVOR_AddVS(p->uM,D*N,0.01);
  3739. for(i=0; i<N; ++i)
  3740. cmVOR_NormalizeProbability( p->uM + (i*D), D);
  3741. // initialize phiM[D,S]
  3742. cmReal_t phi[D*S];
  3743. for(i=0,j=0; i<D; ++i,++j)
  3744. phi[j] = sin( M_PI*7.0*i/6.0 );
  3745. for(i=0; i<D; ++i,++j)
  3746. phi[j] = cos( M_PI*7.0*i/6.0 );
  3747. for(i=0; i<D; ++i,++j)
  3748. phi[j] = sin( M_PI*3.0*i/2.0 );
  3749. for(i=0; i<D; ++i,++j)
  3750. phi[j] = cos( M_PI*3.0*i/2.0 );
  3751. for(i=0; i<D; ++i,++j)
  3752. phi[j] = 0.5 * sin( M_PI*2.0*i/3.0 );
  3753. for(i=0; i<D; ++i,++j)
  3754. phi[j] = 0.5 * cos( M_PI*2.0*i/3.0 );
  3755. cmVOR_Transpose(p->phiM,phi,D,S);
  3756. return p;
  3757. }
  3758. cmRC_t cmChordFree( cmChord** pp )
  3759. {
  3760. cmRC_t rc = cmOkRC;
  3761. cmChord* p = *pp;
  3762. if( pp == NULL || *pp == NULL )
  3763. return cmOkRC;
  3764. if((rc = cmChordFinal(p)) != cmOkRC )
  3765. return rc;
  3766. cmChmmFree( &p->h );
  3767. cmMemPtrFree(&p->iV);
  3768. cmMemPtrFree(&p->aM);
  3769. cmMemPtrFree(&p->uM);
  3770. cmMemPtrFree(&p->sMM);
  3771. cmMemPtrFree(&p->phiM);
  3772. cmMemPtrFree(&p->tsMeanV);
  3773. cmMemPtrFree(&p->tsVarV);
  3774. cmMemPtrFree(&p->chromaM);
  3775. cmMemPtrFree(&p->tsM);
  3776. cmMemPtrFree(&p->cdtsV);
  3777. cmObjFree(pp);
  3778. return rc;
  3779. }
  3780. cmRC_t cmChordInit( cmChord* p, const cmReal_t* chromaM, unsigned T )
  3781. {
  3782. cmRC_t rc = cmOkRC;
  3783. unsigned i;
  3784. unsigned N = p->N; // count of states
  3785. unsigned K = 1; // count of components per mixture
  3786. unsigned D = p->D; // dimensionality of the observation vector
  3787. unsigned S = p->S; //
  3788. cmReal_t alpha = 6.63261; // alpha norm coeff
  3789. if((rc = cmChordFinal(p)) != cmOkRC )
  3790. return rc;
  3791. // Create the hidden markov model
  3792. cmChmmInit( p->h, N, K, D, p->iV, p->aM);
  3793. // load the GMM's for each markov state
  3794. cmReal_t mixCoeff = 1.0;
  3795. bool diagFl = false;
  3796. for(i=0; i<N; ++i)
  3797. if((rc = cmChmmSetGmm(p->h, i, &mixCoeff, p->uM + (i*D), p->sMM+(i*D*D), diagFl )) != cmOkRC )
  3798. return rc;
  3799. // Allocate memory
  3800. // chromaM[D,T] tsM[S,T] cdtsV[T]
  3801. /*
  3802. unsigned n = ALIGN_T(D*T,cmReal_t) + ALIGN_T(S*T,cmReal_t) + ALIGN_T(T,cmReal_t);
  3803. p->chromaM = cmArrayResizeZ(c, &p->memB, n, cmReal_t);
  3804. p->tsM = p->chromaM + ALIGN_T(D*T,cmReal_t);
  3805. p->cdtsV = p->tsM + ALIGN_T(S*T,cmReal_t);
  3806. p->T = T;
  3807. */
  3808. p->chromaM = cmMemResizeZ( cmReal_t, p->chromaM, p->D*T );
  3809. p->tsM = cmMemResizeZ( cmReal_t, p->tsM, p->S*T );
  3810. p->cdtsV = cmMemResizeZ( cmReal_t, p->cdtsV, p->D*T );
  3811. p->T = T;
  3812. // Allocate local memory
  3813. // qV[], triadIntV[] triadSeqV[] tsNormsV[]
  3814. /*
  3815. n = 2*ALIGN_B(T,unsigned) + ALIGN_B(T,int) + ALIGN_B(T,cmReal_t);
  3816. cmArray mem;
  3817. cmArrayAlloc(c, &mem);
  3818. unsigned* qV = (unsigned*) cmArrayResize(c, &mem, n, char);
  3819. unsigned* triadSeqV = (unsigned*) (qV + ALIGN_T(T,unsigned));
  3820. int* triadIntV = (int*) (triadSeqV + ALIGN_T(T,unsigned));
  3821. cmReal_t* tsNormsV = (cmReal_t*) (triadIntV + ALIGN_T(T,int));
  3822. */
  3823. //unsigned qV[T];
  3824. //unsigned triadSeqV[T];
  3825. //int triadIntV[T];
  3826. //cmReal_t tsNormsV[T];
  3827. unsigned* qV = cmMemAlloc( unsigned, T );
  3828. unsigned* triadSeqV = cmMemAlloc( unsigned, T );
  3829. int* triadIntV = cmMemAlloc( int, T );
  3830. cmReal_t* tsNormsV = cmMemAlloc( cmReal_t, T );
  3831. // Take the alpha norm of chroma and store the result in p->chromaM[]
  3832. for(i=0; i<T; ++i)
  3833. p->chromaM[i] = cmVOR_AlphaNorm( chromaM + (i*D), D, alpha);
  3834. cmVOR_DivVVS(p->chromaM,D*T,chromaM, cmVOR_AlphaNorm(p->chromaM,T,alpha));
  3835. // Train the HMM iniital state prob. p->h->iV[] and transition matrix p->h->aM[]
  3836. unsigned flags = kNoTrainMixCoeffChmmFl | kNoTrainMeanChmmFl | kNoTrainCovarChmmFl;
  3837. unsigned iterCnt = 40;
  3838. if( chromaM != NULL && T > 0 )
  3839. if((rc = cmChmmTrain(p->h, p->chromaM, p->T, iterCnt, 0, flags )) != cmOkRC )
  3840. goto errLabel;
  3841. // Find the most likely chords using a Viterbi decoding of the chroma.
  3842. cmChmmDecode(p->h,p->chromaM,T,qV);
  3843. // Reorder the chord sequence cmcording to circle of fifths
  3844. unsigned map[] = {0, 14, 4, 18, 8, 22, 12, 2, 16, 6, 20, 10, 17, 7, 21, 11, 1, 15, 5, 19, 9, 23, 13, 3 };
  3845. for(i=0; i<T; ++i)
  3846. qV[i] = map[ qV[i] ];
  3847. //cmVOU_PrintL("qV:\n",p->obj.err.rpt,1,T,qV);
  3848. // Smooth the chord sequence with a median filter.
  3849. cmVOU_MedianFilt(qV,T,3,triadSeqV,1);
  3850. //cmVOU_PrintL("triadSeqV:\n",p->obj.err.rpt,1,T,triadSeqV);
  3851. // Calculate the chord change distance on the circle of fifths.
  3852. int d = 0;
  3853. for(i=0; i<T; ++i)
  3854. {
  3855. int v = abs(d);
  3856. assert(v<N);
  3857. v = (v<=11) ? v : -(12-(v-12));
  3858. if( i > 0 )
  3859. triadIntV[i-1] = (d < 0 ? -1 : 1) * v;
  3860. if( i + 1 < T)
  3861. d = triadSeqV[i+1] - triadSeqV[i];
  3862. }
  3863. // Project chroma into a 6D tonal space.
  3864. cmVOR_MultMMM( p->tsM,S,T,p->phiM,p->chromaM,D);
  3865. // Find the norm of p->tsM[6,T]
  3866. cmVOR_Fill(tsNormsV,T,0);
  3867. for(i=0; i<T; ++i)
  3868. tsNormsV[i] = cmVOR_MultSumVV( p->tsM + (i*S), p->tsM + (i*S), S );
  3869. cmVOR_PowVS(tsNormsV,T,0.5);
  3870. // Take the cosine distance.
  3871. p->cdtsV[0] = 1;
  3872. for(i=1; i<T; ++i)
  3873. p->cdtsV[i] = cmVOR_MultSumVV( p->tsM + ((i-1)*S), p->tsM + (i*S), S );
  3874. for(i=0; i<T-1; ++i)
  3875. p->cdtsV[i+1] /= tsNormsV[i] * tsNormsV[i+1];
  3876. //cmVOR_PrintL("tsNormsV:\n",p->obj.err.rpt,1,T,tsNormsV);
  3877. //cmVOR_PrintL("CDTS:\n", p->obj.err.rpt,1,T,p->cdtsV);
  3878. p->triadSeqMode = cmVOU_Mode(triadSeqV,T);
  3879. p->triadSeqVar = cmVOU_Variance(triadSeqV,T,NULL);
  3880. p->triadIntMean = cmVOI_Mean(triadIntV,T);
  3881. p->triadIntVar = cmVOI_Variance(triadIntV,T,&p->triadIntMean);
  3882. cmVOR_MeanM( p->tsMeanV, p->tsM, S, T, 1 );
  3883. cmVOR_VarianceM( p->tsVarV, p->tsM, S, T, p->tsMeanV, 1);
  3884. p->cdtsMean = cmVOR_Mean( p->cdtsV, T );
  3885. p->cdtsVar = cmVOR_Variance( p->cdtsV, T, &p->cdtsMean );
  3886. /*
  3887. cmReal_t tsMt[T*S];
  3888. cmKbRecd kb;
  3889. cmPlotInitialize(NULL);
  3890. cmPlotSetup("Chords",1,1);
  3891. cmCtxPrint(c,"%s\n","press any key");
  3892. //cmPlotLineD( NULL, NULL, p->cdtsV, NULL, T, NULL, kSolidPlotLineId );
  3893. cmVOR_Transpose(tsMt,p->tsM,S,T);
  3894. cmPlotLineMD(NULL, tsMt, NULL, T, S, kSolidPlotLineId);
  3895. cmPlotDraw();
  3896. cmKeyPress(&kb);
  3897. cmPlotFinalize();
  3898. */
  3899. errLabel:
  3900. cmMemPtrFree(&qV);
  3901. cmMemPtrFree(&triadSeqV);
  3902. cmMemPtrFree(&triadIntV);
  3903. cmMemPtrFree(&tsNormsV);
  3904. return rc;
  3905. }
  3906. cmRC_t cmChordFinal( cmChord* p )
  3907. { return cmOkRC; }
  3908. void cmChordTest( cmRpt_t* rpt, cmLHeapH_t lhH, cmSymTblH_t stH )
  3909. {
  3910. cmCtx c;
  3911. cmCtxAlloc(&c,rpt,lhH,stH);
  3912. cmChord* p = cmChordAlloc(&c,NULL,NULL,0);
  3913. cmChordFree(&p);
  3914. }