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.

cmProc2.c 172KB

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