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

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. }