libcm is a C development framework with an emphasis on audio signal processing applications.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

cmDspKr.c 148KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698
  1. //| Copyright: (C) 2009-2020 Kevin Larke <contact AT larke DOT org>
  2. //| License: GNU GPL version 3.0 or above. See the accompanying LICENSE file.
  3. #include "cmPrefix.h"
  4. #include "cmGlobal.h"
  5. #include "cmFloatTypes.h"
  6. #include "cmComplexTypes.h"
  7. #include "cmRpt.h"
  8. #include "cmErr.h"
  9. #include "cmCtx.h"
  10. #include "cmMem.h"
  11. #include "cmMallocDebug.h"
  12. #include "cmLinkedHeap.h"
  13. #include "cmFile.h"
  14. #include "cmSymTbl.h"
  15. #include "cmJson.h"
  16. #include "cmText.h"
  17. #include "cmPrefs.h"
  18. #include "cmDspValue.h"
  19. #include "cmMsgProtocol.h"
  20. #include "cmThread.h"
  21. #include "cmUdpPort.h"
  22. #include "cmUdpNet.h"
  23. #include "cmSerialPort.h"
  24. //( { file_desc:"'snap' audio effects performance analysis units." kw:[snap]}
  25. #include "cmTime.h"
  26. #include "cmAudioSys.h"
  27. #include "cmDspCtx.h"
  28. #include "cmDspClass.h"
  29. #include "cmDspStore.h"
  30. #include "cmDspUi.h"
  31. #include "cmDspSys.h"
  32. #include "cmMath.h"
  33. #include "cmAudioFile.h"
  34. #include "cmFileSys.h"
  35. #include "cmProcObj.h"
  36. #include "cmProcTemplateMain.h"
  37. #include "cmProc.h"
  38. #include "cmMidi.h"
  39. #include "cmProc2.h"
  40. #include "cmVectOpsTemplateMain.h"
  41. #include "cmAudioFile.h"
  42. #include "cmMidiFile.h"
  43. #include "cmTimeLine.h"
  44. #include "cmScore.h"
  45. #include "cmProc4.h"
  46. #include "cmProc5.h"
  47. #include "cmSyncRecd.h"
  48. #include "cmTakeSeqBldr.h"
  49. //------------------------------------------------------------------------------------------------------------
  50. //)
  51. //( { label:cmDspKr file_desc:"Spectral non-linear distortion effect." kw:[sunit gutim] }
  52. enum
  53. {
  54. kWndSmpCntKrId,
  55. kHopFactKrId,
  56. kModeKrId,
  57. kThreshKrId,
  58. kLwrSlopeKrId,
  59. kUprSlopeKrId,
  60. kOffsetKrId,
  61. kInvertKrId,
  62. kBypassKrId,
  63. kWetKrId,
  64. kAudioInKrId,
  65. kAudioOutKrId
  66. };
  67. typedef struct
  68. {
  69. cmDspInst_t inst;
  70. cmCtx* ctx;
  71. cmSpecDist_t* sdp;
  72. } cmDspKr_t;
  73. cmDspClass_t _cmKrDC;
  74. cmDspInst_t* _cmDspKrAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  75. {
  76. cmDspVarArg_t args[] =
  77. {
  78. { "wndn", kWndSmpCntKrId, 0, 0, kInDsvFl | kUIntDsvFl | kReqArgDsvFl, "Window sample count" },
  79. { "hopf", kHopFactKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Hop factor" },
  80. { "mode", kModeKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Mode 0=bypass 1=basic 2=spec cnt 3=amp env" },
  81. { "thrh", kThreshKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Threshold" },
  82. { "lwrs", kLwrSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Lower Slope"},
  83. { "uprs", kUprSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"},
  84. { "offs", kOffsetKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Offset"},
  85. { "invt", kInvertKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Invert"},
  86. { "bypass", kBypassKrId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Bypass enable flag." },
  87. { "wet", kWetKrId, 0, 0, kInDsvFl | kSampleDsvFl, "Wet mix level."},
  88. { "in", kAudioInKrId, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" },
  89. { "out", kAudioOutKrId, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" },
  90. { NULL, 0, 0, 0, 0 }
  91. };
  92. cmDspKr_t* p = cmDspInstAlloc(cmDspKr_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  93. unsigned defWndSmpCnt = cmDspDefaultUInt(&p->inst,kWndSmpCntKrId);
  94. unsigned wndSmpCnt = cmNextPowerOfTwo( defWndSmpCnt );
  95. cmDspSetDefaultUInt( ctx,&p->inst, kWndSmpCntKrId, defWndSmpCnt, wndSmpCnt );
  96. cmDspSetDefaultUInt( ctx,&p->inst, kHopFactKrId, 0, 4 );
  97. cmDspSetDefaultUInt( ctx,&p->inst, kModeKrId, 0, kBasicModeSdId );
  98. cmDspSetDefaultDouble( ctx,&p->inst, kThreshKrId, 0, 60.0 );
  99. cmDspSetDefaultDouble( ctx,&p->inst, kLwrSlopeKrId, 0, 2.0 );
  100. cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKrId, 0, 0.0 );
  101. cmDspSetDefaultDouble( ctx,&p->inst, kOffsetKrId, 0, 30.0);
  102. cmDspSetDefaultUInt( ctx,&p->inst, kInvertKrId, 0, 0 );
  103. cmDspSetDefaultUInt( ctx,&p->inst, kBypassKrId, 0, 0 );
  104. cmDspSetDefaultSample( ctx,&p->inst, kWetKrId, 0, 1.0);
  105. //_cmDspKrCmInit(ctx,p); // initialize the cm library
  106. p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH);
  107. return &p->inst;
  108. }
  109. cmDspRC_t _cmDspKrFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  110. {
  111. cmDspRC_t rc = kOkDspRC;
  112. cmDspKr_t* p = (cmDspKr_t*)inst;
  113. cmSpecDistFree(&p->sdp);
  114. cmCtxFree(&p->ctx);
  115. //_cmDspKrCmFinal(ctx,p); // finalize the cm library
  116. return rc;
  117. }
  118. cmDspRC_t _cmDspKrSetup(cmDspCtx_t* ctx, cmDspKr_t* p )
  119. {
  120. cmDspRC_t rc = kOkDspRC;
  121. unsigned wndSmpCnt = cmDspUInt(&p->inst,kWndSmpCntKrId);
  122. unsigned hopFact = cmDspUInt(&p->inst,kHopFactKrId);
  123. unsigned olaWndTypeId =kHannWndId;
  124. cmSpecDistFree(&p->sdp);
  125. p->sdp = cmSpecDistAlloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId);
  126. assert(p->sdp != NULL );
  127. if((rc = cmDspZeroAudioBuf(ctx,&p->inst,kAudioOutKrId)) != kOkDspRC )
  128. return rc;
  129. return rc;
  130. }
  131. cmDspRC_t _cmDspKrReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  132. {
  133. cmDspKr_t* p = (cmDspKr_t*)inst;
  134. cmDspRC_t rc;
  135. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  136. return rc;
  137. return _cmDspKrSetup(ctx,p);
  138. }
  139. cmDspRC_t _cmDspKrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  140. {
  141. cmDspKr_t* p = (cmDspKr_t*)inst;
  142. cmDspRC_t rc = kOkDspRC;
  143. unsigned iChIdx = 0;
  144. const cmSample_t* ip = cmDspAudioBuf(ctx,inst,kAudioInKrId,iChIdx);
  145. unsigned iSmpCnt = cmDspVarRows(inst,kAudioInKrId);
  146. // if no connected
  147. if( iSmpCnt == 0 )
  148. return rc;
  149. unsigned oChIdx = 0;
  150. cmSample_t* op = cmDspAudioBuf(ctx,inst,kAudioOutKrId,oChIdx);
  151. unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId);
  152. const cmSample_t* sp;
  153. cmSample_t wet = cmDspSample(inst,kWetKrId);
  154. cmSpecDistExec(p->sdp,ip,iSmpCnt);
  155. if((sp = cmSpecDistOut(p->sdp)) != NULL )
  156. {
  157. cmVOS_MultVVS(op,oSmpCnt,sp,wet);
  158. }
  159. if( wet<1.0 )
  160. cmVOS_MultSumVVS(op,oSmpCnt,ip,1.0-wet);
  161. return rc;
  162. }
  163. cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  164. {
  165. cmDspKr_t* p = (cmDspKr_t*)inst;
  166. cmDspRC_t rc = kOkDspRC;
  167. cmDspSetEvent(ctx,inst,evt);
  168. switch( evt->dstVarId )
  169. {
  170. case kWndSmpCntKrId:
  171. case kHopFactKrId:
  172. _cmDspKrSetup(ctx,p);
  173. // THIS IS A HACK
  174. // WHEN WND OR HOP CHANGE THE RESULTING CHANGES
  175. // SHOULD BE ISOLATED IN cmSpecDist() AND THE
  176. // CURRENT STATE OF THE PARAMETERS SHOULD NOT BE
  177. // LOST - IF THE CHANGES WERE ISOLATED WITHIN PVANL
  178. // AND PVSYN IT MIGHT BE POSSIBLE TO DO WITH
  179. // MINIMAL AUDIO INTERUPTION.
  180. p->sdp->mode = cmDspUInt(inst,kModeKrId);
  181. p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
  182. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
  183. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
  184. p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
  185. p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
  186. printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt);
  187. break;
  188. case kModeKrId:
  189. p->sdp->mode = cmDspUInt(inst,kModeKrId);
  190. printf("mode:%i\n",p->sdp->mode);
  191. break;
  192. case kThreshKrId:
  193. p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
  194. //printf("thr:p:%p sdp:%p %f\n",p,p->sdp,p->sdp->thresh);
  195. break;
  196. case kUprSlopeKrId:
  197. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
  198. //printf("upr slope:%f\n",p->sdp->uprSlope);
  199. break;
  200. case kLwrSlopeKrId:
  201. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
  202. //printf("upr slope:%f\n",p->sdp->lwrSlope);
  203. break;
  204. case kOffsetKrId:
  205. p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
  206. break;
  207. case kInvertKrId:
  208. p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
  209. break;
  210. case kWetKrId:
  211. break;
  212. default:
  213. { assert(0); }
  214. }
  215. return rc;
  216. }
  217. cmDspClass_t* cmKrClassCons( cmDspCtx_t* ctx )
  218. {
  219. cmDspClassSetup(&_cmKrDC,ctx,"Kr",
  220. NULL,
  221. _cmDspKrAlloc,
  222. _cmDspKrFree,
  223. _cmDspKrReset,
  224. _cmDspKrExec,
  225. _cmDspKrRecv,
  226. NULL,NULL,
  227. "Fourier based non-linear transformer.");
  228. return &_cmKrDC;
  229. }
  230. //------------------------------------------------------------------------------------------------------------
  231. //)
  232. //( { label:cmDspKr2 file_desc:"Spectral non-linear distortion effect." kw:[sunit gutim] }
  233. enum
  234. {
  235. kWndSmpCntKr2Id,
  236. kHopFactKr2Id,
  237. kCeilKr2Id,
  238. kExpoKr2Id,
  239. kThreshKr2Id,
  240. kLwrSlopeKr2Id,
  241. kUprSlopeKr2Id,
  242. kMixKr2Id,
  243. kWetKr2Id,
  244. kIgainKr2Id,
  245. kAudioInKr2Id,
  246. kAudioOutKr2Id
  247. };
  248. typedef struct
  249. {
  250. cmDspInst_t inst;
  251. cmCtx* ctx;
  252. cmSpecDist2_t* sdp;
  253. } cmDspKr2_t;
  254. cmDspClass_t _cmKr2DC;
  255. cmDspInst_t* _cmDspKr2Alloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  256. {
  257. cmDspVarArg_t args[] =
  258. {
  259. { "wndn", kWndSmpCntKr2Id, 0, 0, kInDsvFl | kUIntDsvFl | kReqArgDsvFl, "Window sample count" },
  260. { "hopf", kHopFactKr2Id, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Hop factor" },
  261. { "ceil", kCeilKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Ceiling" },
  262. { "expo", kExpoKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Exponent" },
  263. { "thrh", kThreshKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Threshold" },
  264. { "lwrs", kLwrSlopeKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Lower Slope"},
  265. { "uprs", kUprSlopeKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"},
  266. { "mix", kMixKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Mix"},
  267. { "wet", kWetKr2Id, 0, 0, kInDsvFl | kSampleDsvFl, "Wet mix level."},
  268. { "igain", kIgainKr2Id, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Input gain."},
  269. { "in", kAudioInKr2Id, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" },
  270. { "out", kAudioOutKr2Id, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" },
  271. { NULL, 0, 0, 0, 0 }
  272. };
  273. cmDspKr2_t* p = cmDspInstAlloc(cmDspKr2_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  274. unsigned defWndSmpCnt = cmDspDefaultUInt(&p->inst,kWndSmpCntKr2Id);
  275. unsigned wndSmpCnt = cmNextPowerOfTwo( defWndSmpCnt );
  276. cmDspSetDefaultUInt( ctx,&p->inst, kWndSmpCntKr2Id, defWndSmpCnt, wndSmpCnt );
  277. cmDspSetDefaultUInt( ctx,&p->inst, kHopFactKr2Id, 0, 4 );
  278. cmDspSetDefaultDouble( ctx,&p->inst, kCeilKr2Id, 0, 20.0 );
  279. cmDspSetDefaultDouble( ctx,&p->inst, kExpoKr2Id, 0, 2.0 );
  280. cmDspSetDefaultDouble( ctx,&p->inst, kThreshKr2Id, 0, 60.0 );
  281. cmDspSetDefaultDouble( ctx,&p->inst, kLwrSlopeKr2Id, 0, 2.0 );
  282. cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKr2Id, 0, 0.0 );
  283. cmDspSetDefaultDouble( ctx,&p->inst, kMixKr2Id, 0, 0.0 );
  284. cmDspSetDefaultSample( ctx,&p->inst, kWetKr2Id, 0, 1.0);
  285. cmDspSetDefaultDouble( ctx,&p->inst, kIgainKr2Id, 0, 0.0 );
  286. //_cmDspKr2CmInit(ctx,p); // initialize the cm library
  287. p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH);
  288. return &p->inst;
  289. }
  290. cmDspRC_t _cmDspKr2Free(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  291. {
  292. cmDspRC_t rc = kOkDspRC;
  293. cmDspKr2_t* p = (cmDspKr2_t*)inst;
  294. cmSpecDist2Free(&p->sdp);
  295. cmCtxFree(&p->ctx);
  296. //_cmDspKr2CmFinal(ctx,p); // finalize the cm library
  297. return rc;
  298. }
  299. cmDspRC_t _cmDspKr2Setup(cmDspCtx_t* ctx, cmDspKr2_t* p )
  300. {
  301. cmDspRC_t rc = kOkDspRC;
  302. unsigned wndSmpCnt = cmDspUInt(&p->inst,kWndSmpCntKr2Id);
  303. unsigned hopFact = cmDspUInt(&p->inst,kHopFactKr2Id);
  304. unsigned olaWndTypeId =kHannWndId;
  305. cmSpecDist2Free(&p->sdp);
  306. p->sdp = cmSpecDist2Alloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId);
  307. assert(p->sdp != NULL );
  308. if((rc = cmDspZeroAudioBuf(ctx,&p->inst,kAudioOutKr2Id)) != kOkDspRC )
  309. return rc;
  310. return rc;
  311. }
  312. cmDspRC_t _cmDspKr2Reset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  313. {
  314. cmDspKr2_t* p = (cmDspKr2_t*)inst;
  315. cmDspRC_t rc;
  316. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  317. return rc;
  318. return _cmDspKr2Setup(ctx,p);
  319. }
  320. cmDspRC_t _cmDspKr2Exec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  321. {
  322. cmDspKr2_t* p = (cmDspKr2_t*)inst;
  323. cmDspRC_t rc = kOkDspRC;
  324. unsigned iChIdx = 0;
  325. const cmSample_t* ip = cmDspAudioBuf(ctx,inst,kAudioInKr2Id,iChIdx);
  326. unsigned iSmpCnt = cmDspVarRows(inst,kAudioInKr2Id);
  327. // if no connected
  328. if( iSmpCnt == 0 )
  329. return rc;
  330. unsigned oChIdx = 0;
  331. cmSample_t* op = cmDspAudioBuf(ctx,inst,kAudioOutKr2Id,oChIdx);
  332. unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKr2Id);
  333. const cmSample_t* sp;
  334. cmSample_t wet = cmDspSample(inst,kWetKr2Id);
  335. cmSpecDist2Exec(p->sdp,ip,iSmpCnt);
  336. if((sp = cmSpecDist2Out(p->sdp)) != NULL )
  337. {
  338. cmVOS_MultVVS(op,oSmpCnt,sp,wet);
  339. }
  340. if( wet<1.0 )
  341. cmVOS_MultSumVVS(op,oSmpCnt,ip,1.0-wet);
  342. return rc;
  343. }
  344. cmDspRC_t _cmDspKr2Recv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  345. {
  346. cmDspKr2_t* p = (cmDspKr2_t*)inst;
  347. cmDspRC_t rc = kOkDspRC;
  348. cmDspSetEvent(ctx,inst,evt);
  349. switch( evt->dstVarId )
  350. {
  351. case kWndSmpCntKr2Id:
  352. case kHopFactKr2Id:
  353. _cmDspKr2Setup(ctx,p);
  354. // THIS IS A HACK
  355. // WHEN WND OR HOP CHANGE THE RESULTING CHANGES
  356. // SHOULD BE ISOLATED IN cmSpecDist() AND THE
  357. // CURRENT STATE OF THE PARAMETERS SHOULD NOT BE
  358. // LOST - IF THE CHANGES WERE ISOLATED WITHIN PVANL
  359. // AND PVSYN IT MIGHT BE POSSIBLE TO DO WITH
  360. // MINIMAL AUDIO INTERUPTION.
  361. p->sdp->ceiling = cmDspDouble(inst,kCeilKr2Id);
  362. p->sdp->expo = cmDspDouble(inst,kExpoKr2Id);
  363. p->sdp->thresh = cmDspDouble(inst,kThreshKr2Id);
  364. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKr2Id);
  365. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKr2Id);
  366. p->sdp->mix = cmDspDouble(inst,kMixKr2Id);
  367. printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt);
  368. break;
  369. case kCeilKr2Id:
  370. p->sdp->ceiling = cmDspDouble(inst,kCeilKr2Id);
  371. break;
  372. case kExpoKr2Id:
  373. p->sdp->expo = cmDspDouble(inst,kExpoKr2Id);
  374. break;
  375. case kThreshKr2Id:
  376. p->sdp->thresh = cmDspDouble(inst,kThreshKr2Id);
  377. break;
  378. case kUprSlopeKr2Id:
  379. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKr2Id);
  380. break;
  381. case kLwrSlopeKr2Id:
  382. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKr2Id);
  383. break;
  384. case kMixKr2Id:
  385. p->sdp->mix = cmDspDouble(inst,kMixKr2Id);
  386. break;
  387. case kWetKr2Id:
  388. break;
  389. case kIgainKr2Id:
  390. p->sdp->igain = cmDspDouble(inst,kIgainKr2Id);
  391. break;
  392. default:
  393. { assert(0); }
  394. }
  395. //cmSpecDist2Report(p->sdp);
  396. return rc;
  397. }
  398. cmDspClass_t* cmKr2ClassCons( cmDspCtx_t* ctx )
  399. {
  400. cmDspClassSetup(&_cmKr2DC,ctx,"Kr2",
  401. NULL,
  402. _cmDspKr2Alloc,
  403. _cmDspKr2Free,
  404. _cmDspKr2Reset,
  405. _cmDspKr2Exec,
  406. _cmDspKr2Recv,
  407. NULL,NULL,
  408. "Fourier based non-linear transformer two.");
  409. return &_cmKr2DC;
  410. }
  411. //------------------------------------------------------------------------------------------------------------
  412. //)
  413. //( { label:cmDspTimeLine file_desc:"Time line user interface unit." kw:[sunit gutim] }
  414. enum
  415. {
  416. kTlFileTlId,
  417. kPrefixPathTlId,
  418. kSelTlId,
  419. kMeasTlId,
  420. kCursTlId,
  421. kResetTlId,
  422. kAudFnTlId,
  423. kAudLblTlId,
  424. kMidiFnTlId,
  425. kMidiLblTlId,
  426. kBegAudSmpIdxTlId,
  427. kEndAudSmpIdxTlId,
  428. kBegMidiSmpIdxTlId,
  429. kEndMidiSmpIdxTlId,
  430. };
  431. cmDspClass_t _cmTimeLineDC;
  432. typedef struct
  433. {
  434. cmDspInst_t inst;
  435. cmTlH_t tlH;
  436. unsigned afIdx;
  437. } cmDspTimeLine_t;
  438. cmDspInst_t* _cmDspTimeLineAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  439. {
  440. cmDspVarArg_t args[] =
  441. {
  442. { "tlfile", kTlFileTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Time line file." },
  443. { "path", kPrefixPathTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Time line data file prefix path" },
  444. { "sel", kSelTlId, 0, 0, kInDsvFl | kOutDsvFl | kUIntDsvFl, "Selected marker id."},
  445. { "meas", kMeasTlId, 0, 0, kInDsvFl | kUIntDsvFl, "Select a bar marker and generate a 'sel' output."},
  446. { "curs", kCursTlId, 0, 0, kInDsvFl | kUIntDsvFl, "Current audio file index."},
  447. { "reset", kResetTlId, 0, 0, kInDsvFl | kSymDsvFl, "Resend all outputs." },
  448. { "afn", kAudFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected Audio file." },
  449. { "albl", kAudLblTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Select Audio file time line label."},
  450. { "mfn", kMidiFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected MIDI file." },
  451. { "mlbl", kMidiLblTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Select MIDI file time line label."},
  452. { "absi", kBegAudSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "Begin audio sample index."},
  453. { "aesi", kEndAudSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "End audio sample index."},
  454. { "mbsi", kBegMidiSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "Begin MIDI sample index."},
  455. { "mesi", kEndMidiSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "End MIDI sample index."},
  456. { NULL, 0, 0, 0, 0 }
  457. };
  458. cmDspTimeLine_t* p = cmDspInstAlloc(cmDspTimeLine_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  459. cmDspSetDefaultUInt( ctx, &p->inst, kSelTlId, 0, cmInvalidId);
  460. cmDspSetDefaultUInt( ctx, &p->inst, kCursTlId, 0, 0);
  461. cmDspSetDefaultStrcz(ctx, &p->inst, kAudFnTlId, NULL, "");
  462. cmDspSetDefaultStrcz(ctx, &p->inst, kAudLblTlId, NULL, "");
  463. cmDspSetDefaultStrcz(ctx, &p->inst, kMidiFnTlId, NULL, "");
  464. cmDspSetDefaultStrcz(ctx, &p->inst, kMidiLblTlId, NULL, "");
  465. cmDspSetDefaultInt( ctx, &p->inst, kBegAudSmpIdxTlId, 0, cmInvalidIdx);
  466. cmDspSetDefaultInt( ctx, &p->inst, kEndAudSmpIdxTlId, 0, cmInvalidIdx);
  467. cmDspSetDefaultInt( ctx, &p->inst, kBegMidiSmpIdxTlId, 0, cmInvalidIdx);
  468. cmDspSetDefaultInt( ctx, &p->inst, kEndMidiSmpIdxTlId, 0, cmInvalidIdx);
  469. // create the UI control
  470. cmDspUiTimeLineCreate(ctx,&p->inst,kTlFileTlId,kPrefixPathTlId,kSelTlId,kMeasTlId,kCursTlId);
  471. p->tlH = cmTimeLineNullHandle;
  472. return &p->inst;
  473. }
  474. cmDspRC_t _cmDspTimeLineFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  475. {
  476. cmDspRC_t rc = kOkDspRC;
  477. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  478. if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
  479. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Time-line finalize failed.");
  480. return rc;
  481. }
  482. cmDspRC_t _cmDspTimeLineReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  483. {
  484. cmDspRC_t rc = kOkDspRC;
  485. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  486. cmDspApplyAllDefaults(ctx,inst);
  487. const cmChar_t* tlFn;
  488. const cmChar_t* tlPrePath = cmDspStrcz(inst,kPrefixPathTlId);
  489. if((tlFn = cmDspStrcz(inst, kTlFileTlId )) != NULL )
  490. if( cmTimeLineInitializeFromFile(ctx->cmCtx, &p->tlH, NULL, NULL, tlFn, tlPrePath ) != kOkTlRC )
  491. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Time-line file open failed.");
  492. return rc;
  493. }
  494. cmDspRC_t _cmDspTimeLineRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  495. {
  496. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  497. switch( evt->dstVarId )
  498. {
  499. case kPrefixPathTlId:
  500. cmDspSetEvent(ctx,inst,evt);
  501. break;
  502. case kCursTlId:
  503. cmDspSetEvent(ctx,inst,evt);
  504. break;
  505. case kResetTlId:
  506. case kSelTlId:
  507. {
  508. unsigned markerId;
  509. cmDspSetEvent(ctx,inst,evt);
  510. // get the id of the selected marker
  511. if((markerId = cmDspUInt(inst,kSelTlId)) != cmInvalidId )
  512. {
  513. // get the marker object
  514. cmTlObj_t* op;
  515. if((op = cmTimeLineIdToObj(p->tlH, cmInvalidId, markerId )) != NULL )
  516. {
  517. assert(op->typeId == kMarkerTlId || op->typeId == kMidiEvtTlId );
  518. p->afIdx = op->begSmpIdx;
  519. cmDspSetInt(ctx, inst, kBegAudSmpIdxTlId, op->begSmpIdx );
  520. cmDspSetInt(ctx, inst, kEndAudSmpIdxTlId, op->begSmpIdx + op->durSmpCnt );
  521. // locate the audio file assoc'd with the marker
  522. cmTlAudioFile_t* afp;
  523. if((afp = cmTimeLineAudioFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL)
  524. {
  525. cmDspSetStrcz(ctx, inst, kAudFnTlId, afp->fn );
  526. cmDspSetStrcz(ctx, inst, kAudLblTlId, afp->obj.name );
  527. }
  528. // locate the midi file assoc'd with the marker
  529. cmTlMidiFile_t* mfp;
  530. if((mfp = cmTimeLineMidiFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL )
  531. {
  532. cmDspSetInt(ctx, inst, kBegMidiSmpIdxTlId, op->seqSmpIdx - mfp->obj.seqSmpIdx );
  533. cmDspSetInt(ctx, inst, kEndMidiSmpIdxTlId, op->seqSmpIdx + op->durSmpCnt - mfp->obj.seqSmpIdx );
  534. cmDspSetStrcz(ctx, inst, kMidiFnTlId, mfp->fn );
  535. cmDspSetStrcz(ctx, inst, kMidiLblTlId,mfp->obj.name );
  536. }
  537. }
  538. }
  539. }
  540. break;
  541. case kMeasTlId:
  542. cmDspSetEvent(ctx,inst,evt);
  543. break;
  544. default:
  545. {assert(0);}
  546. }
  547. return kOkDspRC;
  548. }
  549. cmDspClass_t* cmTimeLineClassCons( cmDspCtx_t* ctx )
  550. {
  551. cmDspClassSetup(&_cmTimeLineDC,ctx,"TimeLine",
  552. NULL,
  553. _cmDspTimeLineAlloc,
  554. _cmDspTimeLineFree,
  555. _cmDspTimeLineReset,
  556. NULL,
  557. _cmDspTimeLineRecv,
  558. NULL,NULL,
  559. "Time Line control.");
  560. return &_cmTimeLineDC;
  561. }
  562. //------------------------------------------------------------------------------------------------------------
  563. //)
  564. //( { label:cmDspScore file_desc:"Musical score user interface unit." kw:[sunit gutim] }
  565. enum
  566. {
  567. kFnScId,
  568. kSelScId,
  569. kSendScId,
  570. kStatusScId,
  571. kD0ScId,
  572. kD1ScId,
  573. kSmpIdxScId,
  574. kLocIdxScId,
  575. kCmdScId,
  576. kEvtIdxScId,
  577. kDynScId,
  578. kValTypeScId,
  579. kValueScId,
  580. kMeasScId,
  581. };
  582. cmDspClass_t _cmScoreDC;
  583. typedef struct
  584. {
  585. cmDspInst_t inst;
  586. cmScH_t scH;
  587. cmDspCtx_t* ctx; // temporary ctx ptr used during cmScore callback in _cmDspScoreRecv()
  588. unsigned printSymId;
  589. } cmDspScore_t;
  590. cmDspInst_t* _cmDspScoreAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  591. {
  592. cmDspVarArg_t args[] =
  593. {
  594. { "fn", kFnScId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." },
  595. { "sel", kSelScId, 0, 0, kInDsvFl | kOutDsvFl | kUIntDsvFl, "Selected score element index input."},
  596. { "send", kSendScId, 0, 0, kInDsvFl | kTypeDsvMask, "Resend last selected score element."},
  597. { "status", kStatusScId, 0, 0, kInDsvFl | kIntDsvFl, "Performed MIDI status value output" },
  598. { "d0", kD0ScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performed MIDI msg data byte 0" },
  599. { "d1", kD1ScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performed MIDI msg data byte 1" },
  600. { "smpidx", kSmpIdxScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performed MIDi msg time tag as a sample index." },
  601. { "loc", kLocIdxScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performance score location."},
  602. { "cmd", kCmdScId, 0, 0, kInDsvFl | kSymDsvFl, "cmd: dump "},
  603. { "evtidx", kEvtIdxScId, 0, 0, kOutDsvFl | kUIntDsvFl, "Performed event index of following dynamcis level."},
  604. { "dyn", kDynScId, 0, 0, kOutDsvFl | kUIntDsvFl, "Dynamic level of previous event index."},
  605. { "type", kValTypeScId,0, 0, kOutDsvFl | kUIntDsvFl, "Output variable type."},
  606. { "value", kValueScId, 0, 0, kOutDsvFl | kDoubleDsvFl, "Output variable value."},
  607. { "meas", kMeasScId, 0, 0, kInDsvFl | kUIntDsvFl, "Trigger this measures location to emit from 'sel'."},
  608. { NULL, 0, 0, 0, 0 }
  609. };
  610. cmDspScore_t* p = cmDspInstAlloc(cmDspScore_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  611. cmDspSetDefaultUInt( ctx, &p->inst, kSelScId, 0, cmInvalidId);
  612. p->printSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"dump");
  613. // create the UI control
  614. cmDspUiScoreCreate(ctx,&p->inst,kFnScId,kSelScId,kSmpIdxScId,kD0ScId,kD1ScId,kLocIdxScId,kEvtIdxScId,kDynScId,kValTypeScId,kValueScId,kMeasScId);
  615. p->scH = cmScNullHandle;
  616. return &p->inst;
  617. }
  618. cmDspRC_t _cmDspScoreFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  619. {
  620. cmDspRC_t rc = kOkDspRC;
  621. cmDspScore_t* p = (cmDspScore_t*)inst;
  622. if( cmScoreFinalize(&p->scH) != kOkTlRC )
  623. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Score finalize failed.");
  624. return rc;
  625. }
  626. // Callback from cmScore triggered from _cmDspScoreRecv() during call to cmScoreSetPerfEvent().
  627. void _cmDspScoreCb( void* arg, const void* data, unsigned byteCnt )
  628. {
  629. cmDspInst_t* inst = (cmDspInst_t*)arg;
  630. cmDspScore_t* p = (cmDspScore_t*)inst;
  631. cmScMsg_t m;
  632. if( cmScoreDecode(data,byteCnt,&m) == kOkScRC )
  633. {
  634. switch( m.typeId )
  635. {
  636. case kDynMsgScId:
  637. cmDspSetUInt( p->ctx,inst, kEvtIdxScId, m.u.dyn.evtIdx );
  638. cmDspSetUInt( p->ctx,inst, kDynScId, m.u.dyn.dynLvl );
  639. break;
  640. case kVarMsgScId:
  641. cmDspSetUInt( p->ctx,inst, kValTypeScId, m.u.meas.varId);
  642. cmDspSetDouble(p->ctx,inst, kValueScId, m.u.meas.value);
  643. break;
  644. default:
  645. { assert(0); }
  646. }
  647. }
  648. }
  649. cmDspRC_t _cmDspScoreReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  650. {
  651. cmDspRC_t rc = kOkDspRC;
  652. cmDspScore_t* p = (cmDspScore_t*)inst;
  653. const cmChar_t* tlFn = NULL;
  654. unsigned* dynRefArray = NULL;
  655. unsigned dynRefCnt = 0;
  656. cmDspApplyAllDefaults(ctx,inst);
  657. if( cmDspRsrcUIntArray(ctx->dspH, &dynRefCnt, &dynRefArray, "dynRef", NULL ) != kOkDspRC )
  658. {
  659. rc = cmErrMsg(&inst->classPtr->err, kRsrcNotFoundDspRC, "The dynamics reference array resource was not found.");
  660. goto errLabel;
  661. }
  662. if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL )
  663. {
  664. if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, ctx->stH ) != kOkTlRC )
  665. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
  666. //else
  667. // cmScorePrintLoc(p->scH);
  668. }
  669. errLabel:
  670. return rc;
  671. }
  672. cmDspRC_t _cmDspScoreRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  673. {
  674. cmDspScore_t* p = (cmDspScore_t*)inst;
  675. if( evt->dstVarId == kSendScId )
  676. {
  677. unsigned selIdx;
  678. if((selIdx = cmDspUInt(inst,kSelScId)) != cmInvalidIdx )
  679. {
  680. cmDspSetUInt(ctx,inst,kSelScId, selIdx );
  681. cmScoreClearPerfInfo(p->scH);
  682. }
  683. return kOkDspRC;
  684. }
  685. cmDspSetEvent(ctx,inst,evt);
  686. switch( evt->dstVarId )
  687. {
  688. case kSelScId:
  689. cmScoreClearPerfInfo(p->scH);
  690. break;
  691. case kStatusScId:
  692. //printf("st:%x\n",cmDspUInt(inst,kStatusScId));
  693. break;
  694. case kLocIdxScId:
  695. {
  696. assert( cmDspUInt(inst,kStatusScId ) == kNoteOnMdId );
  697. p->ctx = ctx; // setup p->ctx for use in _cmDspScoreCb()
  698. // this call may result in callbacks to _cmDspScoreCb()
  699. cmScoreExecPerfEvent(p->scH, cmDspUInt(inst,kLocIdxScId), cmDspUInt(inst,kSmpIdxScId), cmDspUInt(inst,kD0ScId), cmDspUInt(inst,kD1ScId) );
  700. }
  701. break;
  702. case kCmdScId:
  703. if( cmDspSymbol(inst,kCmdScId) == p->printSymId )
  704. cmScorePrintLoc(p->scH);
  705. break;
  706. case kMeasScId:
  707. break;
  708. }
  709. return kOkDspRC;
  710. }
  711. cmDspClass_t* cmScoreClassCons( cmDspCtx_t* ctx )
  712. {
  713. cmDspClassSetup(&_cmScoreDC,ctx,"Score",
  714. NULL,
  715. _cmDspScoreAlloc,
  716. _cmDspScoreFree,
  717. _cmDspScoreReset,
  718. NULL,
  719. _cmDspScoreRecv,
  720. NULL,NULL,
  721. "Score control.");
  722. return &_cmScoreDC;
  723. }
  724. //------------------------------------------------------------------------------------------------------------
  725. //)
  726. //( { label:cmDspMidiFilePlay file_desc:"MIDI file player." kw:[sunit gutim] }
  727. enum
  728. {
  729. kFnMfId,
  730. kSelMfId,
  731. kBsiMfId,
  732. kEsiMfId,
  733. kStatusMfId,
  734. kD0MfId,
  735. kD1MfId,
  736. kSmpIdxMfId,
  737. kIdMfId
  738. };
  739. cmDspClass_t _cmMidiFilePlayDC;
  740. typedef struct
  741. {
  742. cmDspInst_t inst;
  743. cmMidiFileH_t mfH;
  744. unsigned curMsgIdx; // current midi file msg index
  745. int csi; // current sample index
  746. int bsi; // starting sample index
  747. int esi; // ending sample index
  748. unsigned startSymId;
  749. unsigned stopSymId;
  750. unsigned contSymId;
  751. bool errFl;
  752. } cmDspMidiFilePlay_t;
  753. // 'bsi' and 'esi' give the starting and ending sample for MIDI file playback.
  754. // These indexes are relative to the start of the file.
  755. // When the player recieves a 'start' msg it sets the current sample index
  756. // 'si' to 'bsi' and begins scanning for the next note to play.
  757. // On each call to the _cmDspMidiFilePlayExec() msgs that fall in the interval
  758. // si:si+sPc-1 will be transmitted. (where sPc are the number of samples per DSP cycle).
  759. cmDspInst_t* _cmDspMidiFilePlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  760. {
  761. cmDspVarArg_t args[] =
  762. {
  763. { "fn", kFnMfId, 0, 0, kInDsvFl | kStrzDsvFl, "File name"},
  764. { "sel", kSelMfId, 0, 0, kInDsvFl | kSymDsvFl, "start | stop | continue" },
  765. { "bsi", kBsiMfId, 0, 0, kInDsvFl | kIntDsvFl, "Starting sample." },
  766. { "esi", kEsiMfId, 0, 0, kInDsvFl | kIntDsvFl, "Ending sample."},
  767. { "status", kStatusMfId, 0, 0, kOutDsvFl | kIntDsvFl, "Status value output" },
  768. { "d0", kD0MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 0" },
  769. { "d1", kD1MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 1" },
  770. { "smpidx", kSmpIdxMfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Msg time tag as a sample index." },
  771. { "id", kIdMfId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI file msg unique id."},
  772. { NULL, 0, 0, 0, 0 }
  773. };
  774. cmDspMidiFilePlay_t* p = cmDspInstAlloc(cmDspMidiFilePlay_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  775. p->startSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"start");
  776. p->stopSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"stop");
  777. p->contSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"continue");
  778. p->mfH = cmMidiFileNullHandle;
  779. cmDspSetDefaultStrcz( ctx, &p->inst, kFnMfId, NULL, "");
  780. cmDspSetDefaultSymbol(ctx, &p->inst, kSelMfId, p->stopSymId);
  781. cmDspSetDefaultInt( ctx, &p->inst, kBsiMfId, 0, 0);
  782. cmDspSetDefaultInt( ctx, &p->inst, kEsiMfId, 0, 0);
  783. cmDspSetDefaultUInt( ctx, &p->inst, kStatusMfId, 0, 0);
  784. cmDspSetDefaultUInt( ctx, &p->inst, kD0MfId, 0, 0);
  785. cmDspSetDefaultUInt( ctx, &p->inst, kD1MfId, 0, 0);
  786. return &p->inst;
  787. }
  788. cmDspRC_t _cmDspMidiFilePlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  789. {
  790. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  791. if( cmMidiFileClose(&p->mfH) )
  792. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "MIDI file close failed.");
  793. return kOkDspRC;
  794. }
  795. // return the index of the msg following smpIdx
  796. unsigned _cmDspMidiFilePlaySeekMsgIdx( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned smpIdx )
  797. {
  798. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  799. if( cmMidiFileIsValid(p->mfH) == false )
  800. {
  801. cmErrMsg(&inst->classPtr->err, kInvalidStateDspRC,"The MIDI file player has not been given a valid MIDI file.");
  802. return cmInvalidIdx;
  803. }
  804. unsigned i;
  805. unsigned n = cmMidiFileMsgCount(p->mfH);
  806. const cmMidiTrackMsg_t** a = cmMidiFileMsgArray(p->mfH);
  807. for(i=0; i<n; ++i)
  808. if( (a[i]->amicro * cmDspSampleRate(ctx) / 1000000.0) >= smpIdx )
  809. break;
  810. return i==n ? cmInvalidIdx : i;
  811. }
  812. cmDspRC_t _cmDspMidiFilePlayOpen(cmDspCtx_t* ctx, cmDspInst_t* inst )
  813. {
  814. cmDspRC_t rc = kOkDspRC;
  815. const cmChar_t* fn = cmDspStrcz(inst,kFnMfId);
  816. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  817. p->errFl = false;
  818. if( fn==NULL || strlen(fn)==0 )
  819. return rc;
  820. if( cmMidiFileOpen( ctx->cmCtx, &p->mfH, fn ) != kOkFileRC )
  821. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "MIDI file open failed.");
  822. else
  823. {
  824. p->curMsgIdx = 0;
  825. p->bsi = cmDspInt(inst,kBsiMfId);
  826. p->esi = cmDspInt(inst,kEsiMfId);
  827. p->csi = 0;
  828. // force the first msg to occurr one quarter note into the file
  829. cmMidiFileSetDelay(p->mfH, cmMidiFileTicksPerQN(p->mfH) );
  830. // convert midi msg times to absolute time in samples
  831. //cmMidiFileTickToSamples(p->mfH,cmDspSampleRate(ctx),true);
  832. }
  833. return rc;
  834. }
  835. cmDspRC_t _cmDspMidiFilePlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  836. {
  837. cmDspApplyAllDefaults(ctx,inst);
  838. return _cmDspMidiFilePlayOpen(ctx,inst);
  839. }
  840. cmDspRC_t _cmDspMidiFilePlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  841. {
  842. cmDspRC_t rc = kOkDspRC;
  843. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  844. unsigned sPc = cmDspSamplesPerCycle(ctx);
  845. if( cmDspSymbol(inst,kSelMfId) != p->stopSymId )
  846. {
  847. if( cmMidiFileIsValid(p->mfH) == false )
  848. {
  849. if( p->errFl==false )
  850. {
  851. rc = cmErrMsg(&inst->classPtr->err, kInvalidStateDspRC,"The MIDI file player has not been given a valid MIDI file.");
  852. p->errFl = true;
  853. }
  854. return rc;
  855. }
  856. const cmMidiTrackMsg_t** mpp = cmMidiFileMsgArray(p->mfH);
  857. unsigned msgN = cmMidiFileMsgCount(p->mfH);
  858. do
  859. {
  860. if( p->curMsgIdx >= msgN )
  861. break;
  862. const cmMidiTrackMsg_t* mp = mpp[p->curMsgIdx];
  863. // convert the absolute time in microseconds to samples
  864. unsigned curMsgTimeSmp = round(mp->amicro * cmDspSampleRate(ctx) / 1000000.0);
  865. // if this midi event falls inside this execution window
  866. if( p->csi > curMsgTimeSmp || curMsgTimeSmp >= (p->csi + sPc))
  867. break;
  868. switch( mp->status )
  869. {
  870. case kNoteOffMdId:
  871. case kNoteOnMdId:
  872. case kCtlMdId:
  873. cmDspSetUInt(ctx,inst, kSmpIdxMfId, curMsgTimeSmp);
  874. cmDspSetUInt(ctx,inst, kD1MfId, mp->u.chMsgPtr->d1);
  875. cmDspSetUInt(ctx,inst, kD0MfId, mp->u.chMsgPtr->d0);
  876. cmDspSetUInt(ctx,inst, kStatusMfId, mp->status);
  877. cmDspSetUInt(ctx,inst, kIdMfId, mp->uid);
  878. break;
  879. }
  880. p->curMsgIdx += 1;
  881. }while(1);
  882. }
  883. p->csi += sPc;
  884. return rc;
  885. }
  886. cmDspRC_t _cmDspMidiFilePlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  887. {
  888. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  889. cmDspSetEvent(ctx,inst,evt);
  890. switch(evt->dstVarId)
  891. {
  892. case kFnMfId:
  893. _cmDspMidiFilePlayOpen(ctx, inst );
  894. break;
  895. case kSelMfId:
  896. {
  897. if( cmDspSymbol(inst,kSelMfId)==p->startSymId )
  898. {
  899. p->csi = cmDspInt(inst,kBsiMfId);
  900. p->curMsgIdx = _cmDspMidiFilePlaySeekMsgIdx(ctx, inst, p->csi );
  901. }
  902. break;
  903. }
  904. }
  905. return kOkDspRC;
  906. }
  907. cmDspClass_t* cmMidiFilePlayClassCons( cmDspCtx_t* ctx )
  908. {
  909. cmDspClassSetup(&_cmMidiFilePlayDC,ctx,"MidiFilePlay",
  910. NULL,
  911. _cmDspMidiFilePlayAlloc,
  912. _cmDspMidiFilePlayFree,
  913. _cmDspMidiFilePlayReset,
  914. _cmDspMidiFilePlayExec,
  915. _cmDspMidiFilePlayRecv,
  916. NULL,NULL,
  917. "MIDI file player.");
  918. return &_cmMidiFilePlayDC;
  919. }
  920. //------------------------------------------------------------------------------------------------------------
  921. //)
  922. //( { label:cmDspScFol file_desc:"MIDI performance score follower." kw:[sunit gutim] }
  923. enum
  924. {
  925. kFnSfId,
  926. kBufCntSfId,
  927. kMaxWndCntSfId,
  928. kMinVelSfId,
  929. kMeasflSfId,
  930. kIndexSfId,
  931. kMuidSfId,
  932. kStatusSfId,
  933. kD0SfId,
  934. kD1SfId,
  935. kSmpIdxSfId,
  936. kCmdSfId,
  937. kOutSfId,
  938. kRecentSfId,
  939. kVlocSfId,
  940. kVtypSfId,
  941. kVvalSfId,
  942. kVcostSfId,
  943. kSymSfId
  944. };
  945. cmDspClass_t _cmScFolDC;
  946. struct cmDspScFol_str;
  947. typedef struct
  948. {
  949. cmDspCtx_t* ctx;
  950. struct cmDspScFol_str* sfp;
  951. } cmDspScFolCbArg_t;
  952. typedef struct cmDspScFol_str
  953. {
  954. cmDspInst_t inst;
  955. cmScMatcher* sfp;
  956. cmScMeas* smp;
  957. cmScH_t scH;
  958. cmDspScFolCbArg_t arg;
  959. unsigned printSymId;
  960. unsigned quietSymId;
  961. unsigned maxScLocIdx;
  962. bool liveFl;
  963. } cmDspScFol_t;
  964. cmDspInst_t* _cmDspScFolAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  965. {
  966. cmDspVarArg_t args[] =
  967. {
  968. { "fn", kFnSfId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." },
  969. { "bufcnt",kBufCntSfId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Event buffer element count." },
  970. { "wndcnt",kMaxWndCntSfId,0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Maximum window length."},
  971. { "minvel",kMinVelSfId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Minimum velocity."},
  972. { "measfl",kMeasflSfId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Enable measurements"},
  973. { "index", kIndexSfId, 0, 0, kInDsvFl | kUIntDsvFl, "Tracking start location."},
  974. { "muid", kMuidSfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI msg file unique id"},
  975. { "status",kStatusSfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI status byte"},
  976. { "d0", kD0SfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI data byte 0"},
  977. { "d1", kD1SfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI data byte 1"},
  978. { "smpidx",kSmpIdxSfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI time tag as a sample index"},
  979. { "cmd", kCmdSfId, 0, 0, kInDsvFl | kSymDsvFl, "Command input: print | quiet"},
  980. { "out", kOutSfId, 0, 0, kOutDsvFl| kUIntDsvFl, "Maximum score location index."},
  981. { "recent",kRecentSfId, 0, 0, kOutDsvFl| kUIntDsvFl, "Most recent score location index."},
  982. { "vloc", kVlocSfId, 0, 0, kOutDsvFl| kUIntDsvFl, "Score location at which the variable value becomes active."},
  983. { "vtyp", kVtypSfId, 0, 0, kOutDsvFl| kUIntDsvFl, "Variable type: 0=even=kEvenVarScId 1=dyn=kDynVarScId 2=tempo=kTempoVarScId."},
  984. { "vval", kVvalSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Variable value."},
  985. { "vcost", kVcostSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Variable match cost value."},
  986. { "sym", kSymSfId, 0, 0, kOutDsvFl| kSymDsvFl, "Symbol associated with a global variable which has changed value."},
  987. { NULL, 0, 0, 0, 0, NULL }
  988. };
  989. cmDspScFol_t* p;
  990. if((p = cmDspInstAlloc(cmDspScFol_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl)) == NULL )
  991. return NULL;
  992. p->sfp = cmScMatcherAlloc(ctx->cmProcCtx, NULL, 0, cmScNullHandle, 0, 0, NULL, NULL );
  993. p->smp = cmScMeasAlloc( ctx->cmProcCtx, NULL, cmScNullHandle, 0, NULL, 0 );
  994. p->printSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"print");
  995. p->quietSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"quiet");
  996. p->maxScLocIdx= cmInvalidIdx;
  997. cmDspSetDefaultUInt( ctx, &p->inst, kBufCntSfId, 0, 7);
  998. cmDspSetDefaultUInt( ctx, &p->inst, kMaxWndCntSfId, 0, 10);
  999. cmDspSetDefaultUInt( ctx, &p->inst, kMinVelSfId, 0, 5);
  1000. cmDspSetDefaultBool( ctx, &p->inst, kMeasflSfId, 0, 0);
  1001. cmDspSetDefaultUInt( ctx, &p->inst, kIndexSfId, 0, 0);
  1002. cmDspSetDefaultUInt( ctx, &p->inst, kOutSfId, 0, 0);
  1003. cmDspSetDefaultUInt( ctx, &p->inst, kRecentSfId, 0, 0);
  1004. cmDspSetDefaultSymbol(ctx,&p->inst, kCmdSfId, p->quietSymId );
  1005. return &p->inst;
  1006. }
  1007. cmDspRC_t _cmDspScFolFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1008. {
  1009. cmDspScFol_t* p = (cmDspScFol_t*)inst;
  1010. cmScMatcherFree(&p->sfp);
  1011. cmScMeasFree(&p->smp);
  1012. cmScoreFinalize(&p->scH);
  1013. return kOkDspRC;
  1014. }
  1015. // This is a callback function from cmScMatcherExec() which is called when
  1016. // this cmDspFol object receives a new score location index.
  1017. void _cmScFolMatcherCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
  1018. {
  1019. cmDspScFolCbArg_t* ap = (cmDspScFolCbArg_t*)arg;
  1020. if( cmScMeasExec(ap->sfp->smp, rp->mni, rp->locIdx, rp->scEvtIdx, rp->flags, rp->smpIdx, rp->pitch, rp->vel ) == cmOkRC )
  1021. {
  1022. cmDspInst_t* inst = &(ap->sfp->inst);
  1023. // send 'set' values that were calculated on the previous call to cmScMeasExec()
  1024. unsigned i;
  1025. for(i=ap->sfp->smp->vsi; i<ap->sfp->smp->nsi; ++i)
  1026. if(ap->sfp->smp->set[i].value != DBL_MAX )
  1027. {
  1028. // switch( ap->sfp->smp->set[i].sp->varId )
  1029. // {
  1030. // case kEvenVarScId:
  1031. // cmDspSetDouble(ap->ctx,inst,kEvenSfId,ap->sfp->smp->set[i].value);
  1032. // break;
  1033. //
  1034. // case kDynVarScId:
  1035. // cmDspSetDouble(ap->ctx,inst,kDynSfId,ap->sfp->smp->set[i].value);
  1036. // break;
  1037. //
  1038. // case kTempoVarScId:
  1039. // cmDspSetDouble(ap->ctx,inst,kTempoSfId,ap->sfp->smp->set[i].value);
  1040. // break;
  1041. //
  1042. // default:
  1043. // { assert(0); }
  1044. // }
  1045. //
  1046. // cmDspSetDouble(ap->ctx,inst,kCostSfId,ap->sfp->smp->set[i].match_cost);
  1047. // Set the values in the global variable storage
  1048. cmDspValue_t vv,cv;
  1049. unsigned j;
  1050. cmDsvSetDouble(&vv,ap->sfp->smp->set[i].value);
  1051. cmDsvSetDouble(&cv,ap->sfp->smp->set[i].match_cost);
  1052. for(j=0; j<ap->sfp->smp->set[i].sp->sectCnt; ++j)
  1053. {
  1054. cmDspStoreSetValueViaSym(ap->ctx->dsH, ap->sfp->smp->set[i].sp->symArray[j], &vv );
  1055. cmDspStoreSetValueViaSym(ap->ctx->dsH, ap->sfp->smp->set[i].sp->costSymArray[j], &cv );
  1056. cmDspSetSymbol(ap->ctx,inst,kSymSfId,ap->sfp->smp->set[i].sp->symArray[j]);
  1057. cmDspSetSymbol(ap->ctx,inst,kSymSfId,ap->sfp->smp->set[i].sp->costSymArray[j]);
  1058. if( cmDspBool(inst,kMeasflSfId) )
  1059. {
  1060. cmDspSetUInt( ap->ctx, inst, kVlocSfId, ap->sfp->smp->set[i].sp->sectArray[j]->locPtr->index);
  1061. cmDspSetDouble( ap->ctx, inst, kVvalSfId, ap->sfp->smp->set[i].value);
  1062. cmDspSetDouble( ap->ctx, inst, kVcostSfId, ap->sfp->smp->set[i].match_cost);
  1063. cmDspSetUInt( ap->ctx, inst, kVtypSfId, ap->sfp->smp->set[i].sp->varId);
  1064. }
  1065. }
  1066. }
  1067. // // trigger 'section' starts
  1068. // for(i=ap->sfp->smp->vsli; i<ap->sfp->smp->nsli; ++i)
  1069. // {
  1070. // const cmScoreLoc_t* locPtr = cmScoreLoc(ap->sfp->smp->mp->scH,i);
  1071. // if( locPtr->begSectPtr != NULL )
  1072. // cmDspSetUInt(ap->ctx,inst,kSectIndexSfId,locPtr->begSectPtr->index);
  1073. // }
  1074. }
  1075. }
  1076. cmDspRC_t _cmDspScFolOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
  1077. {
  1078. cmDspRC_t rc = kOkDspRC;
  1079. cmDspScFol_t* p = (cmDspScFol_t*)inst;
  1080. const cmChar_t* fn;
  1081. if((fn = cmDspStrcz(inst,kFnSfId)) == NULL || strlen(fn)==0 )
  1082. return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied.");
  1083. if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
  1084. return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
  1085. if( cmScoreIsValid(p->scH) )
  1086. {
  1087. unsigned* dynRefArray = NULL;
  1088. unsigned dynRefCnt = 0;
  1089. // initialize the cmScMatcher
  1090. if( cmScMatcherInit(p->sfp, cmDspSampleRate(ctx), p->scH, cmDspUInt(inst,kMaxWndCntSfId), cmDspUInt(inst,kBufCntSfId), _cmScFolMatcherCb, p->smp ) != cmOkRC )
  1091. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Internal score follower allocation failed.");
  1092. // read the dynamics reference array
  1093. if( cmDspRsrcUIntArray(ctx->dspH, &dynRefCnt, &dynRefArray, "dynRef", NULL ) != kOkDspRC )
  1094. {
  1095. rc = cmErrMsg(&inst->classPtr->err, kRsrcNotFoundDspRC, "The dynamics reference array resource was not found.");
  1096. goto errLabel;
  1097. }
  1098. // initialize the cmScMeas object.
  1099. if( cmScMeasInit(p->smp, p->scH, cmDspSampleRate(ctx), dynRefArray, dynRefCnt ) != cmOkRC )
  1100. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Internal scMeas object initialization failed.");
  1101. }
  1102. errLabel:
  1103. return rc;
  1104. }
  1105. cmDspRC_t _cmDspScFolReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1106. {
  1107. cmDspRC_t rc;
  1108. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  1109. return rc;
  1110. return _cmDspScFolOpenScore(ctx,inst);
  1111. }
  1112. cmDspRC_t _cmDspScFolRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1113. {
  1114. cmDspRC_t rc = kOkDspRC;
  1115. cmDspScFol_t* p = (cmDspScFol_t*)inst;
  1116. if((rc = cmDspSetEvent(ctx,inst,evt)) == kOkDspRC && p->sfp != NULL )
  1117. {
  1118. switch( evt->dstVarId )
  1119. {
  1120. case kIndexSfId:
  1121. if( cmScoreIsValid(p->scH) )
  1122. {
  1123. p->maxScLocIdx = cmInvalidIdx;
  1124. if( cmScMeasReset( p->smp ) != cmOkRC )
  1125. cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Score measure unit reset to score index '%i' failed.");
  1126. if( cmScMatcherReset( p->sfp, cmDspUInt(inst,kIndexSfId) ) != cmOkRC )
  1127. cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Score follower reset to score index '%i' failed.");
  1128. }
  1129. break;
  1130. case kStatusSfId:
  1131. if( cmScoreIsValid(p->scH))
  1132. {
  1133. unsigned scLocIdx = cmInvalidIdx;
  1134. // setup the cmScMeas() callback arg.
  1135. p->arg.ctx = ctx;
  1136. p->arg.sfp = p;
  1137. p->sfp->cbArg = &p->arg;
  1138. // this call may result in a callback to _cmScFolMatcherCb()
  1139. if( cmScMatcherExec(p->sfp, cmDspUInt(inst,kSmpIdxSfId), cmDspUInt(inst,kMuidSfId), cmDspUInt(inst,kStatusSfId), cmDspUInt(inst,kD0SfId), cmDspUInt(inst,kD1SfId), &scLocIdx) == cmOkRC )
  1140. if( scLocIdx != cmInvalidIdx )
  1141. {
  1142. // It is possible that the internal score follower may go backwards.
  1143. // In this case it will report a given score location multiple times or out of time order.
  1144. // The 'out' port will only be updated under the circumstances that no later
  1145. // score location has been seen - so the last output from 'out' always reports
  1146. // the furthest possible progress in the score. THe 'recent' output simply reports
  1147. // the most recent output from the internal score follower which may include
  1148. // previously reported or out of order score locations.
  1149. cmDspSetUInt(ctx,inst,kRecentSfId,scLocIdx);
  1150. if( p->maxScLocIdx==cmInvalidIdx || p->maxScLocIdx < scLocIdx )
  1151. {
  1152. p->maxScLocIdx = scLocIdx;
  1153. cmDspSetUInt(ctx,inst,kOutSfId,scLocIdx);
  1154. }
  1155. }
  1156. }
  1157. break;
  1158. case kFnSfId:
  1159. _cmDspScFolOpenScore(ctx,inst);
  1160. break;
  1161. case kCmdSfId:
  1162. if( cmDspSymbol(inst,kCmdSfId) == p->printSymId )
  1163. p->sfp->printFl = true;
  1164. else
  1165. if( cmDspSymbol(inst,kCmdSfId) == p->quietSymId )
  1166. p->sfp->printFl = false;
  1167. break;
  1168. }
  1169. }
  1170. return rc;
  1171. }
  1172. cmDspClass_t* cmScFolClassCons( cmDspCtx_t* ctx )
  1173. {
  1174. cmDspClassSetup(&_cmScFolDC,ctx,"ScFol",
  1175. NULL,
  1176. _cmDspScFolAlloc,
  1177. _cmDspScFolFree,
  1178. _cmDspScFolReset,
  1179. NULL,
  1180. _cmDspScFolRecv,
  1181. NULL,NULL,
  1182. "Score Follower");
  1183. return &_cmScFolDC;
  1184. }
  1185. //------------------------------------------------------------------------------------------------------------
  1186. //)
  1187. //( { label:cmDspScMod file_desc:"Score driven parameter automation." kw:[sunit gutim] }
  1188. enum
  1189. {
  1190. kScLocIdxMdId,
  1191. kResetIdxMdId,
  1192. kCmdMdId,
  1193. kSelMdId,
  1194. kPostMdId
  1195. };
  1196. cmDspClass_t _cmModulatorDC;
  1197. typedef struct
  1198. {
  1199. cmDspInst_t inst;
  1200. cmScModulator* mp;
  1201. cmDspCtx_t* tmp_ctx; // used to temporarily hold the current cmDspCtx during callback
  1202. cmChar_t* fn;
  1203. cmChar_t* modLabel;
  1204. unsigned onSymId;
  1205. unsigned offSymId;
  1206. unsigned postSymId;
  1207. unsigned dumpSymId;
  1208. unsigned minInVarId;
  1209. unsigned maxInVarId;
  1210. unsigned* inVarIdMap;
  1211. unsigned inVarIdOffs;
  1212. } cmDspScMod_t;
  1213. void _cmDspScModCb( void* arg, unsigned varSymId, double value, bool postFl )
  1214. {
  1215. cmDspScMod_t* p = (cmDspScMod_t*)arg;
  1216. cmDspVar_t* varPtr;
  1217. if((varPtr = cmDspVarSymbolToPtr( p->tmp_ctx, &p->inst, varSymId, 0 )) == NULL )
  1218. return;
  1219. cmDspSetDouble(p->tmp_ctx,&p->inst,varPtr->constId,value);
  1220. if( postFl )
  1221. cmDspSetSymbol(p->tmp_ctx,&p->inst,kPostMdId,p->postSymId);
  1222. }
  1223. cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1224. {
  1225. va_list vl1;
  1226. va_copy(vl1,vl);
  1227. cmDspVarArg_t args[] =
  1228. {
  1229. { "index", kScLocIdxMdId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower index input."},
  1230. { "reset", kResetIdxMdId, 0,0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reset the modulator and go to the score index."},
  1231. { "cmd", kCmdMdId, 0,0, kInDsvFl | kSymDsvFl | kOptArgDsvFl, "on | off."},
  1232. { "sel", kSelMdId, 0,0, kInDsvFl | kSymDsvFl | kOptArgDsvFl, "Set the next active entry group name."},
  1233. { "post", kPostMdId, 0,0, kOutDsvFl | kSymDsvFl, "Sends 'post' symbol after a message transmission if the 'post' flag is set in scMod."},
  1234. { NULL, 0, 0, 0, 0 }
  1235. };
  1236. // validate the argument count
  1237. if( va_cnt != 2 )
  1238. {
  1239. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The Modulator requires at least two arguments.");
  1240. return NULL;
  1241. }
  1242. // read the modulator file and label strings
  1243. const cmChar_t* fn = va_arg(vl1,const cmChar_t*);
  1244. const cmChar_t* modLabel = va_arg(vl1,const cmChar_t*);
  1245. va_end(vl1);
  1246. // validate the file
  1247. if( fn==NULL || cmFsIsFile(fn)==false )
  1248. {
  1249. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The Modulator file '%s' is not valid.",cmStringNullGuard(fn));
  1250. return NULL;
  1251. }
  1252. // allocate the internal modulator object
  1253. cmScModulator* mp = cmScModulatorAlloc(ctx->cmProcCtx, NULL, ctx->cmCtx, ctx->stH, cmDspSampleRate(ctx), cmDspSamplesPerCycle(ctx), fn, modLabel, _cmDspScModCb, NULL );
  1254. if(mp == NULL )
  1255. {
  1256. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The internal modulator object initialization failed.");
  1257. return NULL;
  1258. }
  1259. unsigned fixArgCnt = sizeof(args)/sizeof(args[0]) - 1;
  1260. unsigned outVarCnt = cmScModulatorOutVarCount(mp);
  1261. unsigned inVarCnt = cmScModulatorInVarCount(mp);
  1262. unsigned argCnt = fixArgCnt + inVarCnt + outVarCnt;
  1263. cmDspVarArg_t a[ argCnt+1 ];
  1264. unsigned i;
  1265. unsigned* inVarIdMap = cmMemAllocZ( unsigned, inVarCnt );
  1266. cmDspArgCopy( a, argCnt, 0, args, fixArgCnt );
  1267. for(i=fixArgCnt; i<argCnt; ++i)
  1268. {
  1269. unsigned inVarIdx = i - fixArgCnt;
  1270. unsigned outVarIdx = inVarIdx - inVarCnt;
  1271. bool inputFl = inVarIdx < inVarCnt;
  1272. const cmScModVar_t* vp = inputFl ? cmScModulatorInVar(mp,inVarIdx) : cmScModulatorOutVar(mp,outVarIdx);
  1273. const cmChar_t* label = cmSymTblLabel( ctx->stH, vp->varSymId );
  1274. const cmChar_t* docStr = cmTsPrintfS("Variable %s for %s",inputFl?"input":"output",label);
  1275. unsigned flags = inputFl ? kInDsvFl : kOutDsvFl;
  1276. if( inputFl )
  1277. inVarIdMap[ inVarIdx ] = vp->varSymId;
  1278. cmDspArgSetup(ctx, a + i, label, cmInvalidId, i, 0, 0, flags | kDoubleDsvFl, docStr );
  1279. }
  1280. cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
  1281. cmDspScMod_t* p = cmDspInstAlloc(cmDspScMod_t,ctx,classPtr,a,instSymId,id,storeSymId,va_cnt,vl);
  1282. p->fn = cmMemAllocStr(fn);
  1283. p->modLabel = cmMemAllocStr(modLabel);
  1284. p->mp = mp;
  1285. p->onSymId = cmSymTblId(ctx->stH,"on");
  1286. p->offSymId = cmSymTblId(ctx->stH,"off");
  1287. p->postSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"post");
  1288. p->dumpSymId = cmSymTblId(ctx->stH,"dump");
  1289. p->minInVarId = fixArgCnt;
  1290. p->maxInVarId = p->minInVarId + inVarCnt - 1;
  1291. p->inVarIdMap = inVarIdMap;
  1292. p->inVarIdOffs = fixArgCnt;
  1293. mp->cbArg = p; // set the modulator callback arg
  1294. cmDspSetDefaultUInt(ctx,&p->inst,kScLocIdxMdId,0,0);
  1295. cmDspSetDefaultSymbol(ctx,&p->inst,kCmdMdId,p->offSymId);
  1296. cmDspSetDefaultSymbol(ctx,&p->inst,kSelMdId,cmInvalidId);
  1297. return &p->inst;
  1298. }
  1299. cmDspRC_t _cmDspScModFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1300. {
  1301. cmDspRC_t rc = kOkDspRC;
  1302. cmDspScMod_t* p = (cmDspScMod_t*)inst;
  1303. if( cmScModulatorFree(&p->mp) != kOkTlRC )
  1304. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Modulator release failed.");
  1305. cmMemFree(p->fn);
  1306. cmMemFree(p->modLabel);
  1307. cmMemFree(p->inVarIdMap);
  1308. return rc;
  1309. }
  1310. cmDspRC_t _cmDspScModReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1311. {
  1312. cmDspRC_t rc = kOkDspRC;
  1313. cmDspApplyAllDefaults(ctx,inst);
  1314. return rc;
  1315. }
  1316. cmDspRC_t _cmDspScModRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1317. {
  1318. cmDspScMod_t* p = (cmDspScMod_t*)inst;
  1319. cmDspSetEvent(ctx,inst,evt);
  1320. if( p->minInVarId <= evt->dstVarId && evt->dstVarId <= p->maxInVarId )
  1321. {
  1322. double v = cmDspDouble(inst,evt->dstVarId);
  1323. //printf("%s : %i %f\n",__FUNCTION__,evt->dstVarId,v);
  1324. cmScModulatorSetValue( p->mp, p->inVarIdMap[ evt->dstVarId - p->inVarIdOffs ], v );
  1325. }
  1326. switch( evt->dstVarId )
  1327. {
  1328. case kResetIdxMdId:
  1329. cmDspSetUInt(ctx,inst,kScLocIdxMdId,cmDspUInt(inst,kResetIdxMdId));
  1330. break;
  1331. case kCmdMdId:
  1332. {
  1333. unsigned symId = cmDspSymbol(inst,kCmdMdId);
  1334. if( symId == p->onSymId )
  1335. cmScModulatorReset(p->mp, ctx->cmCtx, cmDspUInt(inst,kScLocIdxMdId), cmDspSymbol(inst,kSelMdId));
  1336. if( symId == p->dumpSymId )
  1337. cmScModulatorDump(p->mp);
  1338. }
  1339. break;
  1340. }
  1341. return kOkDspRC;
  1342. }
  1343. cmDspRC_t _cmDspScModExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1344. {
  1345. cmDspRC_t rc = kOkDspRC;
  1346. cmDspScMod_t* p = (cmDspScMod_t*)inst;
  1347. if( cmDspSymbol(inst,kCmdMdId) != p->offSymId )
  1348. {
  1349. p->tmp_ctx = ctx;
  1350. cmScModulatorExec(p->mp,cmDspUInt(inst,kScLocIdxMdId));
  1351. }
  1352. return rc;
  1353. }
  1354. cmDspClass_t* cmScModClassCons( cmDspCtx_t* ctx )
  1355. {
  1356. cmDspClassSetup(&_cmModulatorDC,ctx,"ScMod",
  1357. NULL,
  1358. _cmDspScModAlloc,
  1359. _cmDspScModFree,
  1360. _cmDspScModReset,
  1361. _cmDspScModExec,
  1362. _cmDspScModRecv,
  1363. NULL,NULL,
  1364. "Score Driven Variable Modulator.");
  1365. return &_cmModulatorDC;
  1366. }
  1367. //------------------------------------------------------------------------------------------------------------
  1368. //)
  1369. //( { label:cmDspGSwitch file_desc:"Route all inputs to one of a group of outputs." kw:[sunit gutim] }
  1370. enum
  1371. {
  1372. kInChCntGsId,
  1373. kOutGroupCntGsId,
  1374. kGroupSelIdxGsId,
  1375. kBaseInFloatGsId
  1376. };
  1377. cmDspClass_t _cmGSwitchDC;
  1378. typedef struct
  1379. {
  1380. cmDspInst_t inst;
  1381. unsigned iChCnt;
  1382. unsigned oGroupCnt;
  1383. unsigned baseInFloatGsId;
  1384. unsigned baseInSymGsId;
  1385. unsigned baseInBoolGsId;
  1386. unsigned baseOutFloatGsId;
  1387. unsigned baseOutSymGsId;
  1388. unsigned baseOutBoolGsId;
  1389. } cmDspGSwitch_t;
  1390. cmDspInst_t* _cmDspGSwitchAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1391. {
  1392. va_list vl1;
  1393. va_copy(vl1,vl);
  1394. cmDspVarArg_t args[] =
  1395. {
  1396. { "ichs", kInChCntGsId, 0,0, kUIntDsvFl | kReqArgDsvFl, "Input channel count."},
  1397. { "ochs", kOutGroupCntGsId, 0,0, kUIntDsvFl | kReqArgDsvFl, "Output group count."},
  1398. { "sel", kGroupSelIdxGsId, 0,0, kInDsvFl | kUIntDsvFl, "Group select index."},
  1399. { NULL, 0, 0, 0, 0 }
  1400. };
  1401. // validate the argument count
  1402. if( va_cnt != 2 )
  1403. {
  1404. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The GSwitch requires at least two arguments.");
  1405. return NULL;
  1406. }
  1407. // read the input ch and output group count
  1408. unsigned iChCnt = va_arg(vl1,unsigned);
  1409. unsigned oGroupCnt = va_arg(vl1,unsigned);
  1410. va_end(vl1);
  1411. // validate the channel counts
  1412. if( iChCnt == 0 || oGroupCnt==0 )
  1413. {
  1414. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The GSwitch input channel count and group count must be greater than zero.");
  1415. return NULL;
  1416. }
  1417. unsigned typeCnt = 3; // i.e. float,sym,bool
  1418. unsigned baseInFloatGsId = kBaseInFloatGsId;
  1419. unsigned baseInSymGsId = baseInFloatGsId + iChCnt;
  1420. unsigned baseInBoolGsId = baseInSymGsId + iChCnt;
  1421. unsigned baseOutFloatGsId = baseInBoolGsId + iChCnt;
  1422. unsigned baseOutSymGsId = baseOutFloatGsId + (iChCnt * oGroupCnt);
  1423. unsigned baseOutBoolGsId = baseOutSymGsId + (iChCnt * oGroupCnt);
  1424. unsigned fixArgCnt = 3;
  1425. unsigned varArgCnt = (iChCnt * typeCnt) + (iChCnt * typeCnt * oGroupCnt);
  1426. unsigned argCnt = fixArgCnt + varArgCnt;
  1427. cmDspVarArg_t a[ argCnt+1 ];
  1428. unsigned i;
  1429. cmDspArgCopy( a, argCnt, 0, args, fixArgCnt );
  1430. cmDspArgSetupN( ctx, a, argCnt, baseInFloatGsId, iChCnt, "f-in", baseInFloatGsId, 0, 0, kInDsvFl | kDoubleDsvFl, "Float input");
  1431. cmDspArgSetupN( ctx, a, argCnt, baseInSymGsId, iChCnt, "s-in", baseInSymGsId, 0, 0, kInDsvFl | kSymDsvFl, "Symbol input");
  1432. cmDspArgSetupN( ctx, a, argCnt, baseInBoolGsId, iChCnt, "b-in", baseInBoolGsId, 0, 0, kInDsvFl | kBoolDsvFl, "Bool input");
  1433. unsigned labelCharCnt = 63;
  1434. cmChar_t label[labelCharCnt+1];
  1435. label[labelCharCnt] = 0;
  1436. unsigned gsid = baseOutFloatGsId;
  1437. for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
  1438. {
  1439. snprintf(label,labelCharCnt,"f-out-%i",i);
  1440. cmDspArgSetupN( ctx, a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kDoubleDsvFl, "Float output");
  1441. }
  1442. gsid = baseOutSymGsId;
  1443. for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
  1444. {
  1445. snprintf(label,labelCharCnt,"s-out-%i",i);
  1446. cmDspArgSetupN( ctx, a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kSymDsvFl, "Symbol output");
  1447. }
  1448. gsid = baseOutBoolGsId;
  1449. for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
  1450. {
  1451. snprintf(label,labelCharCnt,"b-out-%i",i);
  1452. cmDspArgSetupN( ctx,a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kBoolDsvFl, "Bool output");
  1453. }
  1454. cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
  1455. cmDspGSwitch_t* p = cmDspInstAlloc(cmDspGSwitch_t,ctx,classPtr,a,instSymId,id,storeSymId,va_cnt,vl);
  1456. p->iChCnt = iChCnt;
  1457. p->oGroupCnt = oGroupCnt;
  1458. p->baseInFloatGsId = baseInFloatGsId;
  1459. p->baseInSymGsId = baseInSymGsId;
  1460. p->baseInBoolGsId = baseInBoolGsId;
  1461. p->baseOutFloatGsId = baseOutFloatGsId;
  1462. p->baseOutSymGsId = baseOutSymGsId;
  1463. p->baseOutBoolGsId = baseOutBoolGsId;
  1464. cmDspSetDefaultUInt(ctx,&p->inst,kGroupSelIdxGsId,0,0);
  1465. return &p->inst;
  1466. }
  1467. cmDspRC_t _cmDspGSwitchReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1468. {
  1469. cmDspRC_t rc = kOkDspRC;
  1470. cmDspApplyAllDefaults(ctx,inst);
  1471. return rc;
  1472. }
  1473. cmDspRC_t _cmDspGSwitchRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1474. {
  1475. cmDspRC_t rc = kOkDspRC;
  1476. cmDspGSwitch_t* p = (cmDspGSwitch_t*)inst;
  1477. // if this is the group selector
  1478. if( evt->dstVarId == kGroupSelIdxGsId )
  1479. {
  1480. unsigned idx;
  1481. if( (idx = cmDsvGetUInt(evt->valuePtr)) > p->oGroupCnt )
  1482. cmDspInstErr(ctx,inst,kInvalidArgDspRC,"The GSwitch group select index %i is out of range %i.",idx,p->oGroupCnt);
  1483. else
  1484. cmDspSetEvent(ctx,inst,evt);
  1485. return rc;
  1486. }
  1487. // get the group selector
  1488. unsigned groupIdx = cmDspUInt(inst,kGroupSelIdxGsId);
  1489. assert( groupIdx < p->oGroupCnt);
  1490. // if this is a float input
  1491. if( p->baseInFloatGsId <= evt->dstVarId && evt->dstVarId < p->baseInFloatGsId + p->iChCnt )
  1492. {
  1493. unsigned outVarId = p->baseOutFloatGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInFloatGsId);
  1494. cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
  1495. return rc;
  1496. }
  1497. // if this is a symbol input
  1498. if( p->baseInSymGsId <= evt->dstVarId && evt->dstVarId < p->baseInSymGsId + p->iChCnt )
  1499. {
  1500. unsigned outVarId = p->baseOutSymGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInSymGsId);
  1501. cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
  1502. return rc;
  1503. }
  1504. // if this is a bool input
  1505. if( p->baseInBoolGsId <= evt->dstVarId && evt->dstVarId < p->baseInBoolGsId + p->iChCnt )
  1506. {
  1507. unsigned outVarId = p->baseOutBoolGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInBoolGsId);
  1508. cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
  1509. return rc;
  1510. }
  1511. return rc;
  1512. }
  1513. cmDspClass_t* cmGSwitchClassCons( cmDspCtx_t* ctx )
  1514. {
  1515. cmDspClassSetup(&_cmGSwitchDC,ctx,"GSwitch",
  1516. NULL,
  1517. _cmDspGSwitchAlloc,
  1518. NULL,
  1519. _cmDspGSwitchReset,
  1520. NULL,
  1521. _cmDspGSwitchRecv,
  1522. NULL,NULL,
  1523. "Ganged switch.");
  1524. return &_cmGSwitchDC;
  1525. }
  1526. //------------------------------------------------------------------------------------------------------------
  1527. //)
  1528. //( { label:cmDspScaleRange file_desc:"Offset and scale a scalar value." kw:[sunit gutim] }
  1529. enum
  1530. {
  1531. kMinInSrId,
  1532. kMaxInSrId,
  1533. kMinOutSrId,
  1534. kMaxOutSrId,
  1535. kValInSrId,
  1536. kValOutSrId,
  1537. };
  1538. cmDspClass_t _cmScaleRangeDC;
  1539. typedef struct
  1540. {
  1541. cmDspInst_t inst;
  1542. } cmDspScaleRange_t;
  1543. cmDspInst_t* _cmDspScaleRangeAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1544. {
  1545. va_list vl1;
  1546. va_copy(vl1,vl);
  1547. cmDspVarArg_t args[] =
  1548. {
  1549. { "min_in", kMinInSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Min Input value."},
  1550. { "max_in", kMaxInSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Max Input value."},
  1551. { "min_out", kMinOutSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Min Output value."},
  1552. { "max_out", kMaxOutSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Max Output value."},
  1553. { "val_in", kValInSrId, 0,0, kInDsvFl | kDoubleDsvFl, "Input value."},
  1554. { "val_out", kValOutSrId, 0,0, kOutDsvFl | kDoubleDsvFl, "Output value"},
  1555. { NULL, 0, 0, 0, 0 }
  1556. };
  1557. cmDspScaleRange_t* p = cmDspInstAlloc(cmDspScaleRange_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  1558. cmDspSetDefaultDouble(ctx,&p->inst,kMinInSrId,0,0);
  1559. cmDspSetDefaultDouble(ctx,&p->inst,kMaxInSrId,0,1.0);
  1560. cmDspSetDefaultDouble(ctx,&p->inst,kMinOutSrId,0,0);
  1561. cmDspSetDefaultDouble(ctx,&p->inst,kMaxOutSrId,0,1.0);
  1562. return &p->inst;
  1563. }
  1564. cmDspRC_t _cmDspScaleRangeReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1565. {
  1566. cmDspRC_t rc = kOkDspRC;
  1567. cmDspApplyAllDefaults(ctx,inst);
  1568. return rc;
  1569. }
  1570. cmDspRC_t _cmDspScaleRangeRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1571. {
  1572. cmDspRC_t rc = kOkDspRC;
  1573. //cmDspScaleRange_t* p = (cmDspScaleRange_t*)inst;
  1574. cmDspSetEvent(ctx,inst,evt);
  1575. if( evt->dstVarId == kValInSrId )
  1576. {
  1577. double val = cmDspDouble(inst,kValInSrId);
  1578. double min_in = cmDspDouble(inst,kMinInSrId);
  1579. double max_in = cmDspDouble(inst,kMaxInSrId);
  1580. double min_out = cmDspDouble(inst,kMinOutSrId);
  1581. double max_out = cmDspDouble(inst,kMaxOutSrId);
  1582. double x = cmMax(min_in,cmMin(max_in,val));
  1583. x = (x - min_in)/(max_in - min_in);
  1584. x = min_out + x * (max_out - min_out);
  1585. cmDspSetDouble(ctx,inst,kValOutSrId, x );
  1586. //printf("%f (%f %f) : (%f %f) %f\n",val,min_in,max_in,min_out,max_out,x);
  1587. }
  1588. return rc;
  1589. }
  1590. cmDspClass_t* cmScaleRangeClassCons( cmDspCtx_t* ctx )
  1591. {
  1592. cmDspClassSetup(&_cmScaleRangeDC,ctx,"ScaleRange",
  1593. NULL,
  1594. _cmDspScaleRangeAlloc,
  1595. NULL,
  1596. _cmDspScaleRangeReset,
  1597. NULL,
  1598. _cmDspScaleRangeRecv,
  1599. NULL,NULL,
  1600. "Scale a value inside an input range to a value in the output range.");
  1601. return &_cmScaleRangeDC;
  1602. }
  1603. //------------------------------------------------------------------------------------------------------------
  1604. //)
  1605. //( { label:cmDspActiveMeas file_desc:"Issue stored parameter values at specified score locations." kw:[sunit gutim] }
  1606. enum
  1607. {
  1608. kCntAmId,
  1609. kSflocAmId,
  1610. kLocAmId,
  1611. kTypeAmId,
  1612. kValueAmId,
  1613. kCstAmId,
  1614. kCmdAmId,
  1615. kScLocAmId,
  1616. kEvenAmId,
  1617. kDynAmId,
  1618. kTempoAmId,
  1619. kCostAmId
  1620. };
  1621. cmDspClass_t _cmActiveMeasDC;
  1622. typedef struct cmDspAmRecd_str
  1623. {
  1624. unsigned loc;
  1625. unsigned type;
  1626. double value;
  1627. double cost;
  1628. struct cmDspAmRecd_str* link;
  1629. } cmDspAmRecd_t;
  1630. //int cmDspActiveMeasRecdCompare(const void * p0, const void * p1)
  1631. //{
  1632. // return ((int)((cmDspActiveMeasRecd_t*)p0)->loc) - (int)(((cmDspActiveMeasRecd_t*)p1)->loc);
  1633. //}
  1634. typedef struct
  1635. {
  1636. cmDspInst_t inst;
  1637. unsigned addSymId;
  1638. unsigned clearSymId;
  1639. unsigned printSymId;
  1640. unsigned rewindSymId;
  1641. cmDspAmRecd_t* array; // array[cnt]
  1642. unsigned cnt;
  1643. cmDspAmRecd_t* list; // first recd in list sorted on 'loc'.
  1644. cmDspAmRecd_t* avail; // next empty recd
  1645. cmDspAmRecd_t* sent; // last recd sent
  1646. } cmDspActiveMeas_t;
  1647. void _cmDspAmAllocList( cmDspActiveMeas_t* p, unsigned cnt )
  1648. {
  1649. assert(p->array == NULL );
  1650. cmDspAmRecd_t* r = cmMemAllocZ(cmDspAmRecd_t,cnt);
  1651. p->cnt = cnt;
  1652. p->array = r;
  1653. p->list = NULL;
  1654. p->avail = r;
  1655. p->sent = NULL;
  1656. }
  1657. cmDspRC_t _cmDspActiveMeasAdd( cmDspCtx_t* ctx, cmDspActiveMeas_t* p, unsigned loc, unsigned type, double value, double cost)
  1658. {
  1659. assert( type != kInvalidVarScId );
  1660. cmDspAmRecd_t* rp = p->list;
  1661. cmDspAmRecd_t* pp = NULL;
  1662. // search for the location to add the new record
  1663. for(; rp!=NULL; rp=rp->link)
  1664. {
  1665. // if this loc and type already exists then replace the value and cost fields
  1666. if( rp->loc==loc && rp->type==type )
  1667. goto foundLabel;
  1668. // if this loc should be inserted before rp
  1669. if( loc < rp->loc )
  1670. break;
  1671. pp = rp;
  1672. }
  1673. // if the pre-allocated list is full
  1674. if( p->avail >= p->array+p->cnt )
  1675. return cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"Unable to store new measurement record. All preallocated active measurement slots are in use.");
  1676. // if prepending to the list
  1677. if( pp == NULL )
  1678. {
  1679. rp = p->avail;
  1680. rp->link = p->list;
  1681. p->list = rp;
  1682. }
  1683. else
  1684. {
  1685. // if appending to the list after pp
  1686. if( rp == NULL )
  1687. {
  1688. // nothing to do
  1689. }
  1690. else // if inserting between pp and rp
  1691. {
  1692. p->avail->link = rp;
  1693. }
  1694. rp = p->avail;
  1695. pp->link = rp;
  1696. }
  1697. p->avail += 1;
  1698. foundLabel:
  1699. rp->loc = loc;
  1700. rp->type = type;
  1701. rp->value = value;
  1702. rp->cost = cost;
  1703. return kOkDspRC;
  1704. }
  1705. cmDspInst_t* _cmDspActiveMeasAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1706. {
  1707. cmDspVarArg_t args[] =
  1708. {
  1709. { "cnt", kCntAmId, 0,0, kInDsvFl | kUIntDsvFl, "Maximum count of active measurements."},
  1710. { "sfloc", kSflocAmId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower location input." },
  1711. { "loc", kLocAmId, 0,0, kInDsvFl | kUIntDsvFl, "Meas. location." },
  1712. { "type", kTypeAmId, 0,0, kInDsvFl | kUIntDsvFl, "Meas. Type. (even,dyn,...)" },
  1713. { "val", kValueAmId, 0,0, kInDsvFl | kDoubleDsvFl, "Meas. Value."},
  1714. { "cst", kCstAmId, 0,0, kInDsvFl | kDoubleDsvFl, "Meas. Cost."},
  1715. { "cmd", kCmdAmId, 0,0, kInDsvFl | kSymDsvFl, "Commands:add | clear | dump | rewind"},
  1716. { "scloc", kScLocAmId, 0,0, kOutDsvFl | kUIntDsvFl, "Score location"},
  1717. { "even", kEvenAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Even out"},
  1718. { "dyn", kDynAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Dyn out"},
  1719. { "tempo", kTempoAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Tempo out"},
  1720. { "cost", kCostAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Cost out"},
  1721. { NULL, 0, 0, 0, 0 }
  1722. };
  1723. cmDspActiveMeas_t* p = cmDspInstAlloc(cmDspActiveMeas_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  1724. p->addSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"add");
  1725. p->clearSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"clear");
  1726. p->printSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"dump");
  1727. p->rewindSymId= cmSymTblRegisterStaticSymbol(ctx->stH,"rewind");
  1728. cmDspSetDefaultUInt( ctx,&p->inst,kCntAmId, 0,256);
  1729. cmDspSetDefaultUInt( ctx,&p->inst,kScLocAmId,0,0);
  1730. cmDspSetDefaultDouble(ctx,&p->inst,kEvenAmId, 0,0);
  1731. cmDspSetDefaultDouble(ctx,&p->inst,kDynAmId, 0,0);
  1732. cmDspSetDefaultDouble(ctx,&p->inst,kTempoAmId,0,0);
  1733. cmDspSetDefaultDouble(ctx,&p->inst,kTempoAmId,0,0);
  1734. return &p->inst;
  1735. }
  1736. cmDspRC_t _cmDspActiveMeasPrint(cmDspCtx_t* ctx, cmDspActiveMeas_t* p )
  1737. {
  1738. cmDspAmRecd_t* rp = p->list;
  1739. for(; rp!=NULL; rp=rp->link)
  1740. {
  1741. const cmChar_t* label = "<null>";
  1742. switch( rp->type )
  1743. {
  1744. case kEvenVarScId: label="even "; break;
  1745. case kDynVarScId: label="dyn "; break;
  1746. case kTempoVarScId: label="tempo"; break;
  1747. default:
  1748. { assert(0); }
  1749. }
  1750. cmRptPrintf(ctx->rpt,"loc:%i %s %f %f\n",rp->loc,label,rp->value,rp->cost);
  1751. }
  1752. return kOkDspRC;
  1753. }
  1754. cmDspRC_t _cmDspActiveMeasClear(cmDspCtx_t* ctx, cmDspActiveMeas_t* p )
  1755. {
  1756. memset(p->array,0,sizeof(p->array[0])*p->cnt);
  1757. p->avail = p->array;
  1758. p->list = NULL;
  1759. p->avail = p->array;
  1760. return kOkDspRC;
  1761. }
  1762. cmDspRC_t _cmDspActiveMeasFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1763. {
  1764. cmDspActiveMeas_t* p = (cmDspActiveMeas_t*)inst;
  1765. cmMemPtrFree(&p->array);
  1766. return kOkDspRC;
  1767. }
  1768. cmDspRC_t _cmDspActiveMeasReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1769. {
  1770. cmDspRC_t rc = kOkDspRC;
  1771. cmDspActiveMeas_t* p = (cmDspActiveMeas_t*)inst;
  1772. cmDspApplyAllDefaults(ctx,inst);
  1773. unsigned cnt = cmMax(100,cmDspUInt(inst,kCntAmId));
  1774. _cmDspActiveMeasFree(ctx,inst,evt);
  1775. _cmDspAmAllocList(p,cnt);
  1776. return rc;
  1777. }
  1778. cmDspRC_t _cmDspActiveMeasRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1779. {
  1780. cmDspRC_t rc = kOkDspRC;
  1781. cmDspActiveMeas_t* p = (cmDspActiveMeas_t*)inst;
  1782. cmDspSetEvent(ctx,inst,evt);
  1783. switch( evt->dstVarId )
  1784. {
  1785. case kSflocAmId:
  1786. {
  1787. unsigned sfloc = cmDspUInt(inst,kSflocAmId); // get the recv'd score location
  1788. cmDspAmRecd_t* rp = p->sent==NULL ? p->list : p->sent->link; // get the next recd to send
  1789. bool fl = false;
  1790. for(; rp!=NULL; rp=rp->link)
  1791. if( rp->loc <= sfloc )
  1792. {
  1793. // deterimine the records type
  1794. unsigned varId = cmInvalidId;
  1795. switch( rp->type )
  1796. {
  1797. case kEvenVarScId: varId = kEvenAmId; break;
  1798. case kDynVarScId: varId = kDynAmId; break;
  1799. case kTempoVarScId: varId = kTempoAmId; break;
  1800. default:
  1801. { assert(0); }
  1802. }
  1803. // Sending the location triggers the avail-ch to switch - so the location should only
  1804. // be sent once.
  1805. if( !fl )
  1806. {
  1807. cmDspSetUInt(ctx,inst,kScLocAmId,rp->loc);
  1808. fl = true;
  1809. }
  1810. // transmit the records value and cost
  1811. cmDspSetDouble(ctx,inst,varId,rp->value);
  1812. cmDspSetDouble(ctx,inst,kCostAmId,rp->cost);
  1813. p->sent = rp;
  1814. }
  1815. }
  1816. break;
  1817. case kCmdAmId:
  1818. {
  1819. unsigned cmdSymId = cmDspSymbol(inst,kCmdAmId);
  1820. if( cmdSymId == p->addSymId )
  1821. rc = _cmDspActiveMeasAdd(ctx,p,cmDspUInt(inst,kLocAmId),cmDspUInt(inst,kTypeAmId),cmDspDouble(inst,kValueAmId),cmDspDouble(inst,kCstAmId));
  1822. else
  1823. if( cmdSymId == p->clearSymId )
  1824. rc = _cmDspActiveMeasClear(ctx,p);
  1825. else
  1826. if( cmdSymId == p->printSymId )
  1827. rc = _cmDspActiveMeasPrint(ctx,p);
  1828. else
  1829. if(cmdSymId == p->rewindSymId )
  1830. p->sent = NULL;
  1831. }
  1832. break;
  1833. }
  1834. // switch( evt->dstVarId )
  1835. // {
  1836. // case kSflocAmId:
  1837. // if( p->nextFullIdx != cmInvalidIdx )
  1838. // {
  1839. // // get the recv'd score location
  1840. // unsigned sflocIdx = cmDspUInt(inst,kSflocAmId);
  1841. //
  1842. // unsigned prvLoc = cmInvalidIdx;
  1843. //
  1844. // // for each remaining avail record
  1845. // for(; p->nextFullIdx < p->nextEmptyIdx; p->nextFullIdx++)
  1846. // {
  1847. // cmDspActiveMeasRecd_t* r = p->array + p->nextFullIdx;
  1848. //
  1849. // // if this records score location is after the recv'd score loc then we're done
  1850. // if( r->loc > sflocIdx )
  1851. // break;
  1852. //
  1853. // // deterimine the records type
  1854. // unsigned varId = cmInvalidId;
  1855. // switch( r->type )
  1856. // {
  1857. // case kEvenVarScId: varId = kEvenAmId; break;
  1858. // case kDynVarScId: varId = kDynAmId; break;
  1859. // case kTempoVarScId: varId = kTempoAmId; break;
  1860. // default:
  1861. // { assert(0); }
  1862. // }
  1863. //
  1864. // // if this score location has not yet been sent then send it now
  1865. // if( prvLoc != r->loc )
  1866. // cmDspSetUInt(ctx,inst,kScLocAmId,r->loc);
  1867. //
  1868. // // transmit the records value and cost
  1869. // cmDspSetDouble(ctx,inst,varId,r->value);
  1870. // cmDspSetDouble(ctx,inst,kCostAmId,r->cost);
  1871. //
  1872. // prvLoc = r->loc;
  1873. // }
  1874. //
  1875. //
  1876. // }
  1877. // break;
  1878. //
  1879. // case kCmdAmId:
  1880. // {
  1881. // unsigned cmdSymId = cmDspSymbol(inst,kCmdAmId);
  1882. //
  1883. // if( cmdSymId == p->addSymId )
  1884. // {
  1885. // if( p->nextEmptyIdx >= p->cnt )
  1886. // cmDspInstErr(ctx,inst,kProcFailDspRC,"The active measurement list is full cnt=%i.",p->cnt);
  1887. // else
  1888. // {
  1889. // cmDspActiveMeasRecd_t* r = p->array + p->nextEmptyIdx;
  1890. // r->loc = cmDspUInt( inst,kLocAmId);
  1891. // r->type = cmDspUInt( inst,kTypeAmId);
  1892. // r->value = cmDspDouble(inst,kValueAmId);
  1893. // r->cost = cmDspDouble(inst,kCstAmId);
  1894. // p->nextEmptyIdx += 1;
  1895. //
  1896. // qsort(p->array,p->nextEmptyIdx,sizeof(p->array[0]),cmDspActiveMeasRecdCompare);
  1897. //
  1898. // if( p->nextEmptyIdx == 1 && p->nextFullIdx == cmInvalidIdx )
  1899. // p->nextFullIdx = 0;
  1900. //
  1901. // }
  1902. // }
  1903. //
  1904. // if( cmdSymId == p->clearSymId )
  1905. // rc = _cmDspActiveMeasClear(ctx,p);
  1906. // else
  1907. // if( cmdSymId == p->printSymId )
  1908. // rc = _cmDspActiveMeasPrint(ctx,p);
  1909. // else
  1910. // if(cmdSymId == p->rewindSymId )
  1911. // p->nextFullIdx = 0;
  1912. // }
  1913. // break;
  1914. //
  1915. // }
  1916. return rc;
  1917. }
  1918. cmDspClass_t* cmActiveMeasClassCons( cmDspCtx_t* ctx )
  1919. {
  1920. cmDspClassSetup(&_cmActiveMeasDC,ctx,"ActiveMeas",
  1921. NULL,
  1922. _cmDspActiveMeasAlloc,
  1923. _cmDspActiveMeasFree,
  1924. _cmDspActiveMeasReset,
  1925. NULL,
  1926. _cmDspActiveMeasRecv,
  1927. NULL,NULL,
  1928. "Scale a value inside an input range to a value in the output range.");
  1929. return &_cmActiveMeasDC;
  1930. }
  1931. //------------------------------------------------------------------------------------------------------------
  1932. //)
  1933. //( { label:cmDspAmSync file_desc:"Calculate MIDI to Audio latency offsets." kw:[sunit gutim] }
  1934. //
  1935. //
  1936. // Usage:
  1937. // 1) In the program resource file setup a list of sync points.
  1938. // 'asmp' refers to a sample offset into the audio file 'af'
  1939. // which should match to the midi event index 'mid' in the
  1940. // midi file 'mf'.
  1941. //
  1942. // amSync :
  1943. // [
  1944. // { af:"af-16" asmp:34735276 mf:"mf-10" mid:350 }
  1945. // { af:"af-16" asmp:71802194 mf:"mf-10" mid:787 }
  1946. // ]
  1947. //
  1948. // 2) Feed the 'fidx' output from a wave table loaded with 'af' into the 'asmp' input port of this amSync object.
  1949. // Feed the 'id' output from the MIDI file player loaded with 'mf' into the 'mid' input port of this amSync object.
  1950. //
  1951. // 3) Run the players.
  1952. // 4) When the run is complete send any message to the 'sel' port of this amSync object.
  1953. // The 'frm:' field of the printed output gives the difference in samples between
  1954. // MIDI and audio sync points.
  1955. //
  1956. // If the value is positive then the MIDI point is after the Audio point.
  1957. // If the value is negative then the MIDI point is before the audio point.
  1958. //
  1959. enum
  1960. {
  1961. kSelAmId,
  1962. kAFnAmId,
  1963. kASmpAmId,
  1964. kMFnAmId,
  1965. kMIdAmId,
  1966. };
  1967. enum
  1968. {
  1969. kAfnAmFl = 0x01,
  1970. kMfnAmFl = 0x02,
  1971. kAsmpAmFl = 0x04,
  1972. kMidAmFl = 0x08,
  1973. };
  1974. cmDspClass_t _cmAmSyncDC;
  1975. typedef struct cmDspAmSyncEntry_str
  1976. {
  1977. const cmChar_t* afn; // audio file name
  1978. const cmChar_t* mfn; // midi file name
  1979. unsigned asmp; // Audio sample index to sync to MIDI event
  1980. unsigned mid; // MIDI event unique id (cmMidiTrackMsg_t.uid)
  1981. int afi; // closest DSP system cycle index to the reference audio sample index (asmp).
  1982. int mfi; // DSP system cycle on which the reference MIDI event (mid) arrived.
  1983. unsigned state; // as incoming msg match this record the state is updated with kXXXAmFl flags
  1984. } cmDspAmSyncEntry_t;
  1985. typedef struct
  1986. {
  1987. cmDspInst_t inst;
  1988. cmDspAmSyncEntry_t* array;
  1989. unsigned arrayCnt;
  1990. cmDspAmSyncEntry_t* acur;
  1991. cmDspAmSyncEntry_t* mcur;
  1992. } cmDspAmSync_t;
  1993. cmDspInst_t* _cmDspAmSyncAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1994. {
  1995. cmDspVarArg_t args[] =
  1996. {
  1997. { "sel", kSelAmId, 0, 0, kInDsvFl | kTypeDsvMask, "Print and reset" },
  1998. { "afn", kAFnAmId, 0, 0, kInDsvFl | kStrzDsvFl, "Audio File name"},
  1999. { "asmp", kASmpAmId, 0, 0, kInDsvFl | kIntDsvFl, "Audio sample index"},
  2000. { "mfn", kMFnAmId, 0, 0, kInDsvFl | kStrzDsvFl, "MIDI File name"},
  2001. { "mid", kMIdAmId, 0, 0, kInDsvFl | kIntDsvFl, "MIDI Event Unique Id"},
  2002. { NULL, 0, 0, 0, 0 }
  2003. };
  2004. cmDspAmSync_t* p = cmDspInstAlloc(cmDspAmSync_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  2005. return &p->inst;
  2006. }
  2007. cmDspRC_t _cmDspAmSyncFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2008. {
  2009. cmDspAmSync_t* p = (cmDspAmSync_t*)inst;
  2010. cmMemFree(p->array);
  2011. return kOkDspRC;
  2012. }
  2013. cmDspRC_t _cmDspAmSyncReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2014. {
  2015. cmDspRC_t rc = kOkDspRC;
  2016. cmDspAmSync_t* p = (cmDspAmSync_t*)inst;
  2017. cmDspApplyAllDefaults(ctx,inst);
  2018. cmJsonH_t jsH = cmDspSysPgmRsrcHandle(ctx->dspH);
  2019. cmJsonNode_t* np;
  2020. const cmChar_t* errLabelPtr;
  2021. unsigned i;
  2022. cmJsRC_t jsRC;
  2023. if((np = cmJsonFindValue(jsH, "amSync", NULL, kArrayTId)) == NULL )
  2024. {
  2025. rc = cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The AUDIO MIDI Sync cfg. record was not found.");
  2026. goto errLabel;
  2027. }
  2028. p->arrayCnt = cmJsonChildCount(np);
  2029. p->array = cmMemResizeZ(cmDspAmSyncEntry_t,p->array,p->arrayCnt);
  2030. for(i=0; i<p->arrayCnt; ++i)
  2031. {
  2032. cmJsonNode_t* anp = cmJsonArrayElement(np,i);
  2033. cmDspAmSyncEntry_t* r = p->array + i;
  2034. if( (jsRC = cmJsonMemberValues(anp,&errLabelPtr,
  2035. "af", kStringTId,&r->afn,
  2036. "asmp",kIntTId, &r->asmp,
  2037. "mf", kStringTId,&r->mfn,
  2038. "mid", kIntTId, &r->mid,
  2039. NULL)) != kOkJsRC )
  2040. {
  2041. if( jsRC == kNodeNotFoundJsRC )
  2042. rc = cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The Audio-MIDI Sync cfg. field '%s' was missing in the cfg. record at index %i.",errLabelPtr,i);
  2043. else
  2044. rc = cmDspInstErr(ctx,inst,kInvalidArgDspRC,"The AUDIO MIDI Sync cfg. parse failed on the record at index %i.",i);
  2045. break;
  2046. }
  2047. r->afi = cmInvalidIdx;
  2048. r->mfi = cmInvalidIdx;
  2049. r->state = 0;
  2050. }
  2051. errLabel:
  2052. return rc;
  2053. }
  2054. cmDspRC_t _cmDspAmSyncRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2055. {
  2056. cmDspAmSync_t* p = (cmDspAmSync_t*)inst;
  2057. unsigned i;
  2058. if( evt->dstVarId != kSelAmId )
  2059. cmDspSetEvent(ctx,inst,evt);
  2060. switch(evt->dstVarId)
  2061. {
  2062. case kSelAmId:
  2063. {
  2064. double srate = cmDspSysSampleRate(ctx->dspH);
  2065. int fpc = cmDspSamplesPerCycle(ctx);
  2066. for(i=0; i<p->arrayCnt; ++i)
  2067. {
  2068. cmDspAmSyncEntry_t* r = p->array + i;
  2069. int dframes = r->mfi-r->afi;
  2070. cmRptPrintf(ctx->rpt,"0x%x : %s %i %i - %s %i %i : frm:%i smp:%i sec:%f\n",
  2071. r->state,
  2072. r->afn,
  2073. r->asmp,
  2074. r->afi,
  2075. r->mfn,
  2076. r->mid,
  2077. r->mfi,
  2078. dframes,
  2079. dframes*fpc,dframes*fpc/srate);
  2080. r->afi = cmInvalidIdx;
  2081. r->mfi = cmInvalidIdx;
  2082. r->state = 0;
  2083. }
  2084. p->acur = NULL;
  2085. p->mcur = NULL;
  2086. }
  2087. break;
  2088. case kAFnAmId:
  2089. {
  2090. // an audio file name just arrived - set p->acur to point to it
  2091. const cmChar_t* fn = cmDspStrcz(inst, kAFnAmId );
  2092. for(i=0; i<p->arrayCnt; ++i)
  2093. if( strcmp(fn,p->array[i].afn) == 0 )
  2094. {
  2095. p->array[i].state = cmSetFlag(p->array[i].state,kAfnAmFl);
  2096. p->acur = p->array + i;
  2097. }
  2098. }
  2099. break;
  2100. case kMFnAmId:
  2101. {
  2102. // a midi file name just arrived - set p->mcur to point to it
  2103. const cmChar_t* fn = cmDspStrcz(inst, kMFnAmId );
  2104. for(i=0; i<p->arrayCnt; ++i)
  2105. if( strcmp(fn,p->array[i].mfn) == 0 )
  2106. {
  2107. p->array[i].state = cmSetFlag(p->array[i].state,kMfnAmFl);
  2108. p->mcur = p->array + i;
  2109. }
  2110. }
  2111. break;
  2112. case kASmpAmId:
  2113. {
  2114. // a audio file sample index has just arrived
  2115. int v = cmDspInt(inst,kASmpAmId);
  2116. // if a valid audio file has been set
  2117. if( p->acur != NULL )
  2118. for(i=0; i<p->arrayCnt; ++i)
  2119. {
  2120. // if the audio sync point is before or on the new audio file sample index then
  2121. // this is the closest audio file index to the audio sync point - record the
  2122. // associated cycleCnt
  2123. cmDspAmSyncEntry_t* r = p->array + i;
  2124. if( cmIsNotFlag(r->state,kAsmpAmFl) && r->asmp <= v && strcmp(p->acur->afn,r->afn)==0 )
  2125. {
  2126. r->afi = ctx->cycleCnt;
  2127. r->state = cmSetFlag(r->state,kAsmpAmFl);
  2128. break;
  2129. }
  2130. }
  2131. }
  2132. break;
  2133. case kMIdAmId:
  2134. {
  2135. // a new MIDI event was received
  2136. int v = cmDspInt(inst,kMIdAmId);
  2137. if( p->mcur != NULL )
  2138. for(i=0; i<p->arrayCnt; ++i)
  2139. {
  2140. // if the new MIDI event matched the MIDI sync point then record the
  2141. // current cycleCnt.
  2142. cmDspAmSyncEntry_t* r = p->array + i;
  2143. if( cmIsNotFlag(r->state,kMidAmFl) && r->mid == v && strcmp(p->mcur->mfn,r->mfn)==0 )
  2144. {
  2145. r->mfi = ctx->cycleCnt;
  2146. r->state = cmSetFlag(r->state,kMidAmFl);
  2147. break;
  2148. }
  2149. }
  2150. }
  2151. break;
  2152. }
  2153. return kOkDspRC;
  2154. }
  2155. cmDspClass_t* cmAmSyncClassCons( cmDspCtx_t* ctx )
  2156. {
  2157. cmDspClassSetup(&_cmAmSyncDC,ctx,"AmSync",
  2158. NULL,
  2159. _cmDspAmSyncAlloc,
  2160. _cmDspAmSyncFree,
  2161. _cmDspAmSyncReset,
  2162. NULL,
  2163. _cmDspAmSyncRecv,
  2164. NULL,NULL,
  2165. "Audio - MIDI Sync Object.");
  2166. return &_cmAmSyncDC;
  2167. }
  2168. //------------------------------------------------------------------------------------------------------------
  2169. //)
  2170. //( { label:cmDspNanoMap file_desc:"Control a MIDI synth." kw:[sunit gutim] }
  2171. enum
  2172. {
  2173. kPgmNmId,
  2174. kStatusNmId,
  2175. kD0NmId,
  2176. kD1NmId,
  2177. kThruNmId
  2178. };
  2179. cmDspClass_t _cmNanoMapDC;
  2180. typedef struct
  2181. {
  2182. cmDspInst_t inst;
  2183. } cmDspNanoMap_t;
  2184. cmDspRC_t _cmDspNanoMapSend( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned st, unsigned d0, unsigned d1 )
  2185. {
  2186. cmDspSetUInt(ctx,inst,kD1NmId,d1);
  2187. cmDspSetUInt(ctx,inst,kD0NmId,d0);
  2188. cmDspSetUInt(ctx,inst,kStatusNmId,st);
  2189. return kOkDspRC;
  2190. }
  2191. void _cmDspNanoMapPgm( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned pgm )
  2192. {
  2193. //cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
  2194. unsigned i;
  2195. for(i=0; i<kMidiChCnt; ++i)
  2196. {
  2197. _cmDspNanoMapSend(ctx,inst,kCtlMdId+i,121,0); // reset all controllers
  2198. _cmDspNanoMapSend(ctx,inst,kCtlMdId+i,123,0); // turn all notes off
  2199. _cmDspNanoMapSend(ctx,inst,kCtlMdId+i,0,0); // switch to bank 0
  2200. _cmDspNanoMapSend(ctx,inst,kPgmMdId+i,pgm,0); // send pgm change
  2201. cmSleepMs(15);
  2202. }
  2203. }
  2204. cmDspInst_t* _cmDspNanoMapAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  2205. {
  2206. cmDspVarArg_t args[] =
  2207. {
  2208. { "pgm", kPgmNmId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reprogram all channels to this pgm." },
  2209. { "status", kStatusNmId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI status" },
  2210. { "d0", kD0NmId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d0" },
  2211. { "d1", kD1NmId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d1" },
  2212. { "thru", kThruNmId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Enable pass through."},
  2213. { NULL, 0, 0, 0, 0 }
  2214. };
  2215. cmDspNanoMap_t* p = cmDspInstAlloc(cmDspNanoMap_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  2216. cmDspSetDefaultUInt(ctx,&p->inst, kPgmNmId, 0, 0 );
  2217. return &p->inst;
  2218. }
  2219. cmDspRC_t _cmDspNanoMapReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2220. {
  2221. cmDspRC_t rc = kOkDspRC;
  2222. cmDspApplyAllDefaults(ctx,inst);
  2223. _cmDspNanoMapPgm(ctx,inst,cmDspUInt(inst,kPgmNmId));
  2224. return rc;
  2225. }
  2226. cmDspRC_t _cmDspNanoMapRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2227. {
  2228. //cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
  2229. switch( evt->dstVarId )
  2230. {
  2231. case kPgmNmId:
  2232. cmDspSetEvent(ctx,inst,evt);
  2233. _cmDspNanoMapPgm(ctx,inst,cmDspUInt(inst,kPgmNmId));
  2234. break;
  2235. case kStatusNmId:
  2236. {
  2237. unsigned status = cmDsvGetUInt(evt->valuePtr);
  2238. unsigned stat_no_ch = status & 0xf0;
  2239. if( stat_no_ch == kNoteOnMdId || stat_no_ch == kNoteOffMdId || stat_no_ch == kCtlMdId )
  2240. {
  2241. //unsigned d0 = cmDspUInt(inst,kD0NmId);
  2242. unsigned ch = 0; //d0 % 8;
  2243. status = (status & 0xf0) + ch;
  2244. cmDspSetUInt(ctx,inst,kStatusNmId,status);
  2245. }
  2246. }
  2247. break;
  2248. default:
  2249. cmDspSetEvent(ctx,inst,evt);
  2250. break;
  2251. }
  2252. return kOkDspRC;
  2253. }
  2254. cmDspClass_t* cmNanoMapClassCons( cmDspCtx_t* ctx )
  2255. {
  2256. cmDspClassSetup(&_cmNanoMapDC,ctx,"NanoMap",
  2257. NULL,
  2258. _cmDspNanoMapAlloc,
  2259. NULL,
  2260. _cmDspNanoMapReset,
  2261. NULL,
  2262. _cmDspNanoMapRecv,
  2263. NULL,
  2264. NULL,
  2265. "Nanosynth Mapper");
  2266. return &_cmNanoMapDC;
  2267. }
  2268. //------------------------------------------------------------------------------------------------------------
  2269. //)
  2270. //( { label:cmDspPicadae file_desc:"Control the Picadae piano mechanism." kw:[sunit gutim] }
  2271. enum
  2272. {
  2273. kStatusPcId,
  2274. kD0PcId,
  2275. kD1PcId,
  2276. kAllOffPcId
  2277. };
  2278. cmDspClass_t _cmPicadaeDC;
  2279. typedef struct
  2280. {
  2281. unsigned pitch;
  2282. unsigned velMapA[10];
  2283. } cmDspPicadaeVelMap_t;
  2284. // This table is generated from picadae_ac_3/velTableToDataStruct.py
  2285. cmDspPicadaeVelMap_t cmDspPicadaeVelMap[] =
  2286. {
  2287. { 21,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2288. { 22,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2289. { 23, { 12800, 12950, 13175, 13500, 13750, 14750, 15375, 17500, 23000, 37000, } },
  2290. { 24, { 12425, 12800, 13175, 14225, 14750, 15500, 17500, 22500, 32000, 39000, } },
  2291. { 25, { 14150, 14375, 14975, 14625, 15500, 16500, 20000, 28500, 40000, 40000, } },
  2292. { 26, { 13000, 13175, 13500, 13700, 13925, 14250, 15000, 16250, 19000, 26500, } },
  2293. { 27, { 13625, 13925, 14075, 14250, 14500, 14875, 15375, 16500, 18750, 25000, } },
  2294. { 28, { 12625, 13750, 13775, 14225, 14500, 16500, 18000, 20000, 25500, 34000, } },
  2295. { 29, { 12125, 12725, 13000, 12950, 14150, 15500, 16250, 17750, 21500, 28000, } },
  2296. { 30, { 13175, 13325, 13550, 14450, 14875, 15500, 16250, 17750, 21500, 27000, } },
  2297. { 31, { 13925, 14075, 14450, 14625, 15500, 16250, 16750, 17750, 19500, 23500, } },
  2298. { 32, { 13250, 14150, 14975, 14750, 15250, 16000, 17500, 21000, 27000, 38000, } },
  2299. { 33, { 11825, 13025, 14075, 14825, 14375, 14875, 16250, 17500, 22000, 28000, } },
  2300. { 34, { 13025, 13375, 13325, 13775, 14375, 14500, 15250, 18000, 22000, 27000, } },
  2301. { 35, { 11375, 12250, 12350, 12725, 14225, 13750, 15375, 17000, 20500, 25000, } },
  2302. { 36, { 11750, 13875, 14125, 14225, 14675, 14750, 16500, 18500, 22500, 32000, } },
  2303. { 37, { 12425, 12575, 13000, 13025, 13375, 15000, 16000, 18750, 25500, 35000, } },
  2304. { 38, { 13750, 13875, 14075, 14600, 14750, 15500, 17750, 21500, 27500, 37000, } },
  2305. { 39, { 11000, 12500, 12950, 13700, 14875, 15500, 16250, 20000, 26500, 37000, } },
  2306. { 40, { 11525, 11750, 12125, 12500, 12875, 13500, 14625, 18250, 23500, 29000, } },
  2307. { 41, { 11675, 11750, 12500, 13000, 13925, 15250, 17000, 20000, 26500, 36000, } },
  2308. { 42, { 11875, 12000, 11975, 12050, 12275, 13375, 15000, 17250, 22000, 29000, } },
  2309. { 43, { 11500, 11625, 11750, 11750, 12625, 12250, 13625, 16750, 19500, 25500, } },
  2310. { 44, { 12425, 12500, 12750, 12650, 13000, 14000, 15250, 16500, 20000, 27000, } },
  2311. { 45, { 11250, 11600, 11875, 12000, 12250, 13100, 14750, 15500, 18250, 25500, } },
  2312. { 46, { 11450, 11525, 11600, 11625, 11875, 12250, 14000, 15750, 17750, 21500, } },
  2313. { 47, { 11900, 11975, 12125, 12375, 13125, 14375, 15750, 18750, 22500, 28500, } },
  2314. { 48, { 11750, 13100, 13325, 13625, 14300, 14975, 15750, 19000, 24000, 30000, } },
  2315. { 49, { 11975, 12050, 12500, 12750, 13125, 14000, 17000, 20000, 25500, 40000, } },
  2316. { 50, { 11625, 11525, 11750, 11825, 12125, 12375, 14750, 16250, 19000, 25500, } },
  2317. { 51, { 12050, 12125, 12125, 12275, 12350, 12500, 12875, 16250, 18500, 22500, } },
  2318. { 52, { 12950, 13025, 13125, 13175, 13250, 13500, 13875, 15750, 18000, 22000, } },
  2319. { 53, { 10600, 10250, 10350, 10450, 10900, 11375, 13025, 14750, 18250, 26500, } },
  2320. { 54, { 12650, 12625, 12725, 12800, 13000, 13625, 16250, 18500, 23000, 32000, } },
  2321. { 55, { 11875, 12125, 12250, 12425, 12875, 13175, 13750, 17250, 20000, 26000, } },
  2322. { 56, { 11625, 11750, 12000, 12200, 12500, 13125, 14375, 17000, 20500, 26500, } },
  2323. { 57, { 11625, 11750, 12125, 12275, 12750, 14625, 16750, 20000, 25500, 39000, } },
  2324. { 58, { 12000, 12500, 12750, 12875, 13100, 13375, 15000, 17750, 21000, 28000, } },
  2325. { 59, { 11625, 11525, 12050, 13375, 13625, 14150, 16500, 21000, 24500, 30000, } },
  2326. { 60, { 12250, 12250, 12375, 12350, 13000, 13500, 16000, 17750, 22000, 29000, } },
  2327. { 61, { 11375, 11500, 11625, 11750, 12000, 12200, 12725, 13625, 17500, 21000, } },
  2328. { 62, { 11600, 11675, 11825, 12125, 12650, 13375, 14375, 18500, 24500, 32000, } },
  2329. { 63, { 12125, 12200, 12350, 12500, 13025, 13625, 16250, 18750, 24500, 36000, } },
  2330. { 64, { 10550, 10650, 10850, 11250, 11875, 12250, 14000, 16250, 19500, 26500, } },
  2331. { 65, { 12750, 12800, 12875, 13175, 13250, 14625, 14975, 17500, 20500, 26000, } },
  2332. { 66, { 10750, 11000, 11250, 11500, 12000, 12875, 15375, 17000, 20500, 28500, } },
  2333. { 67, { 10950, 11125, 11250, 11500, 11875, 13875, 15750, 17750, 23000, 37000, } },
  2334. { 68, { 10150, 10300, 10550, 10800, 11125, 11875, 13000, 16000, 19000, 25000, } },
  2335. { 69, { 11750, 11875, 12375, 12500, 12750, 13500, 16250, 18250, 23500, 31000, } },
  2336. { 70, { 10700, 10850, 10950, 11125, 11625, 13875, 14500, 15750, 18750, 24500, } },
  2337. { 71, { 10200, 10700, 11000, 11250, 11625, 14000, 14875, 16250, 22000, 27000, } },
  2338. { 72, { 9800, 10100, 10400, 10550, 11000, 11625, 13000, 15500, 17750, 23000, } },
  2339. { 73, { 10750, 10900, 11125, 11375, 11625, 12750, 14750, 15500, 18500, 23000, } },
  2340. { 74, { 10300, 10450, 10600, 10850, 11250, 12000, 14250, 15000, 17500, 21000, } },
  2341. { 75, { 10600, 10750, 10900, 11125, 12500, 14500, 14750, 15000, 21000, 31000, } },
  2342. { 76, { 10200, 11625, 12375, 12875, 13500, 15750, 19000, 22500, 27500, 39000, } },
  2343. { 77, { 10500, 10700, 11125, 11375, 11750, 14000, 14875, 16500, 20500, 27000, } },
  2344. { 78, { 10450, 10800, 11000, 11625, 12000, 13125, 15500, 18250, 22000, 34000, } },
  2345. { 79, { 12250, 13500, 14125, 14750, 16250, 17500, 19000, 24500, 31000, 40000, } },
  2346. { 80, { 10400, 10450, 10750, 11125, 12125, 13375, 14750, 17750, 23000, 39000, } },
  2347. { 81, { 10800, 10950, 11125, 11375, 12625, 13875, 14875, 16000, 19000, 23500, } },
  2348. { 82, { 12000, 12375, 13750, 13750, 12625, 14000, 17000, 19000, 21000, 24500, } },
  2349. { 83, { 12250, 12500, 13625, 13875, 14375, 16500, 17750, 20500, 25000, 35000, } },
  2350. { 84, { 11500, 12000, 12250, 12500, 13125, 14250, 15375, 16750, 19500, 25500, } },
  2351. { 85, { 10400, 10500, 10600, 11250, 12250, 13375, 15000, 16750, 20000, 26000, } },
  2352. { 86, { 11500, 11750, 11875, 12000, 12250, 12500, 13500, 15000, 20500, 21000, } },
  2353. { 87, { 10650, 11500, 13125, 13375, 13750, 14500, 16500, 18000, 20000, 24000, } },
  2354. { 88, { 11375, 11375, 11500, 12375, 12000, 13375, 14500, 16500, 19000, 23000, } },
  2355. { 89, { 9200, 10900, 11500, 12125, 22000, 12875, 14125, 16000, 19000, 26500, } },
  2356. { 90, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2357. { 91, { 9450, 9950, 10000, 10150, 10600, 11250, 12125, 13875, 15250, 19000, } },
  2358. { 92, { 9050, 9500, 9600, 10100, 10900, 11875, 13000, 16000, 20500, 31000, } },
  2359. { 93, { 11250, 11375, 12000, 12375, 12875, 13625, 14250, 17500, 21500, 39000, } },
  2360. { 94, { 11125, 11375, 11750, 13500, 14000, 14875, 15750, 17750, 22000, 25500, } },
  2361. { 95, { 10200, 10350, 11500, 12250, 12500, 13125, 13875, 15250, 19000, 21000, } },
  2362. { 96, { 9050, 9550, 10100, 13875, 13000, 14000, 18500, 22000, 27000, 39000, } },
  2363. { 97, { 11000, 12500, 13250, 13000, 13750, 15750, 15000, 18000, 19000, 22500, } },
  2364. { 98, { 10400, 10850, 12125, 12125, 13250, 13875, 16000, 18750, 26500, 37000, } },
  2365. { 99, { 11000, 12625, 13125, 14000, 15500, 16750, 19000, 21500, 25000, 36000, } },
  2366. { 100,{ 9650, 10450, 11500, 12375, 12500, 12875, 13500, 15500, 17500, 21500, } },
  2367. { 101,{ 10950, 11250, 11500, 11875, 12250, 12875, 13500, 14375, 22500, 39000, } },
  2368. { 102,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2369. { 103,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2370. { 104,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2371. { 105,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2372. { 106,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2373. { 107,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2374. { 108,{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } },
  2375. { 0, { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, } }
  2376. };
  2377. typedef struct
  2378. {
  2379. int us;
  2380. int dutyPct;
  2381. } cmDspPicadaeDutyMap_t;
  2382. typedef struct
  2383. {
  2384. unsigned pitch;
  2385. cmDspPicadaeDutyMap_t dutyMapA[5];
  2386. } cmDspPicadaeDuty_t;
  2387. // This table is generated from picadae_ac_3/velTableToDataStruct.py
  2388. cmDspPicadaeDuty_t cmDspPicadaeDutyMap[] =
  2389. {
  2390. {21, {{ -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2391. {22, {{ -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2392. {23, {{ 0, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2393. {24, {{ 0, 75 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2394. {25, {{ 0, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2395. {26, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2396. {27, {{ 0, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2397. {28, {{ 0, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2398. {29, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2399. {30, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2400. {31, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2401. {32, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2402. {33, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2403. {34, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2404. {35, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2405. {36, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2406. {37, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2407. {38, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2408. {39, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2409. {40, {{ 0, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2410. {41, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2411. {42, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2412. {43, {{ 0, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2413. {44, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2414. {45, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2415. {46, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2416. {47, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2417. {48, {{ 0, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2418. {49, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2419. {50, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2420. {51, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2421. {52, {{ 0, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2422. {53, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2423. {54, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2424. {55, {{ 0, 50 }, { 22000, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2425. {56, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2426. {57, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2427. {58, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2428. {59, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2429. {60, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2430. {61, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2431. {62, {{ 0, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2432. {63, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2433. {64, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2434. {65, {{ 0, 50 }, { 17000, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2435. {66, {{ 0, 53 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2436. {67, {{ 0, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2437. {68, {{ 0, 53 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2438. {69, {{ 0, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2439. {70, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2440. {71, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2441. {72, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2442. {73, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2443. {74, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2444. {75, {{ 0, 55 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2445. {76, {{ 0, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2446. {77, {{ 0, 50 }, { 15000, 60 }, { 19000, 70 }, { -1, -1 }, { -1, -1 }, }},
  2447. {78, {{ 0, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2448. {79, {{ 0, 50 }, { 15000, 60 }, { 19000, 70 }, { -1, -1 }, { -1, -1 }, }},
  2449. {80, {{ 0, 45 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2450. {81, {{ 0, 50 }, { 15000, 70 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2451. {82, {{ 0, 50 }, { 12500, 60 }, { 14000, 65 }, { 17000, 70 }, { -1, -1 }, }},
  2452. {83, {{ 0, 50 }, { 15000, 65 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2453. {84, {{ 0, 50 }, { 12500, 60 }, { 14000, 65 }, { 17000, 70 }, { -1, -1 }, }},
  2454. {85, {{ 0, 50 }, { 12500, 60 }, { 14000, 65 }, { 17000, 70 }, { -1, -1 }, }},
  2455. {86, {{ 0, 50 }, { 12500, 60 }, { 14000, 65 }, { 17000, 70 }, { -1, -1 }, }},
  2456. {87, {{ 0, 50 }, { 14000, 60 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2457. {88, {{ 0, 50 }, { 12500, 60 }, { 14000, 65 }, { 17000, 70 }, { -1, -1 }, }},
  2458. {89, {{ 0, 50 }, { 12500, 60 }, { 14000, 65 }, { 17000, 70 }, { -1, -1 }, }},
  2459. {90, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2460. {91, {{ 0, 40 }, { 12500, 50 }, { 14000, 60 }, { 17000, 65 }, { -1, -1 }, }},
  2461. {92, {{ 0, 40 }, { 14000, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2462. {93, {{ 0, 40 }, { 12500, 50 }, { 14000, 60 }, { 17000, 65 }, { -1, -1 }, }},
  2463. {94, {{ 0, 40 }, { 14000, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2464. {95, {{ 0, 40 }, { 12500, 50 }, { 14000, 60 }, { 17000, 65 }, { -1, -1 }, }},
  2465. {96, {{ 0, 40 }, { 12500, 50 }, { 14000, 60 }, { 17000, 65 }, { -1, -1 }, }},
  2466. {97, {{ 0, 40 }, { 14000, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2467. {98, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2468. {99, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2469. {100, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2470. {101, {{ 0, 50 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2471. {102, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2472. {103, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2473. {104, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2474. {105, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2475. {106, {{ -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2476. {107, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2477. {108, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2478. { 0, {{ -1, -1}, { -1, -1 }, { -1, -1 }, { -1, -1 }, { -1, -1 }, }},
  2479. };
  2480. typedef struct
  2481. {
  2482. cmDspInst_t inst;
  2483. unsigned curDutyPctA[127];
  2484. } cmDspPicadae_t;
  2485. unsigned _cmDspPicadaeVelToMicroseconds( unsigned pitch, unsigned vel )
  2486. {
  2487. unsigned i;
  2488. unsigned velN = sizeof(cmDspPicadaeVelMap[i].velMapA)/sizeof(cmDspPicadaeVelMap[i].velMapA[0]);
  2489. long velIdx = lround( vel * velN / 127.0 );
  2490. assert( pitch >= cmDspPicadaeVelMap[0].pitch );
  2491. long pitchIdx = pitch - cmDspPicadaeVelMap[0].pitch;
  2492. return cmDspPicadaeVelMap[pitchIdx].velMapA[velIdx];
  2493. }
  2494. int _cmDspPicadaeVelToDutyCycle( unsigned pitch, unsigned usec )
  2495. {
  2496. unsigned i;
  2497. int dutyPct = -1;
  2498. long pitchIdx = pitch - cmDspPicadaeDutyMap[0].pitch;
  2499. cmDspPicadaeDuty_t* r = cmDspPicadaeDutyMap + pitchIdx;
  2500. for(i=0; r->dutyMapA[i].us != -1; ++i)
  2501. if( r->dutyMapA[i].us <= usec )
  2502. dutyPct = r->dutyMapA[i].dutyPct;
  2503. return dutyPct;
  2504. }
  2505. void _cmDspPicadaeSerialXmitNoteOff( cmDspCtx_t* ctx, cmDspInst_t* inst, uint8_t pitch )
  2506. {
  2507. const uint8_t note_off_op = 3;
  2508. uint8_t serialBuf[] = { 'w', pitch, note_off_op, 1, 0 };
  2509. cmSeSend( cmDspSysSerialPort(ctx->dspH), serialBuf, sizeof(serialBuf) );
  2510. }
  2511. void _cmDspPicadaeSerialXmitNoteOn( cmDspCtx_t* ctx, cmDspInst_t* inst, uint8_t pitch, uint8_t coarse_tick, uint8_t fine_tick )
  2512. {
  2513. const uint8_t note_on_usec_op = 2;
  2514. uint8_t serialBuf[] = { 'w', pitch, note_on_usec_op, 2, coarse_tick, fine_tick };
  2515. cmSeSend( cmDspSysSerialPort(ctx->dspH), serialBuf, sizeof(serialBuf) );
  2516. }
  2517. void _cmDspPicadaeSerialXmitDuty( cmDspCtx_t* ctx, cmDspPicadae_t* p, uint8_t pitch, uint8_t dutyPct )
  2518. {
  2519. if( p->curDutyPctA[ pitch ] != dutyPct )
  2520. {
  2521. uint8_t duty_pct_op = 0;
  2522. unsigned char serialBuf[] = { 'w', pitch, duty_pct_op, 1, dutyPct };
  2523. cmSeSend( cmDspSysSerialPort(ctx->dspH), serialBuf, sizeof(serialBuf) );
  2524. }
  2525. }
  2526. void _cmDspPicadaeSendNote( cmDspCtx_t* ctx, cmDspInst_t* inst )
  2527. {
  2528. cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
  2529. unsigned prescaler_usec = 16;
  2530. unsigned status = cmDspUInt(inst,kStatusPcId);
  2531. uint8_t pitch = (uint8_t)cmDspUInt(inst,kD0PcId);
  2532. unsigned velocity = cmDspUInt(inst,kD1PcId);
  2533. assert( 21<=pitch && pitch<=108 );
  2534. // if this is a note-off
  2535. if( status == kNoteOffMdId || velocity == 0 )
  2536. {
  2537. _cmDspPicadaeSerialXmitNoteOff( ctx, inst, pitch );
  2538. return;
  2539. }
  2540. unsigned usec = _cmDspPicadaeVelToMicroseconds(pitch, velocity );
  2541. // if the pitch is invalid then 'usec' will be set to 0
  2542. if( usec == 0 )
  2543. return;
  2544. unsigned dutyPct = _cmDspPicadaeVelToDutyCycle( pitch, usec );
  2545. // if the pitch is invalid then dutyPct will be set to -1
  2546. if( dutyPct == -1 )
  2547. return;
  2548. unsigned coarse_usec = prescaler_usec*255; // usec's in one coarse tick
  2549. uint8_t coarse_ticks = (uint8_t)(usec / coarse_usec);
  2550. uint8_t fine_ticks = (uint8_t)((usec - coarse_ticks*coarse_usec) / prescaler_usec);
  2551. _cmDspPicadaeSerialXmitDuty( ctx, p, pitch, dutyPct );
  2552. _cmDspPicadaeSerialXmitNoteOn( ctx, inst, pitch, coarse_ticks, fine_ticks );
  2553. }
  2554. cmDspInst_t* _cmDspPicadaeAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  2555. {
  2556. cmDspVarArg_t args[] =
  2557. {
  2558. { "status", kStatusPcId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI status" },
  2559. { "d0", kD0PcId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d0" },
  2560. { "d1", kD1PcId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d1" },
  2561. { "alloff", kAllOffPcId, 0, 0, kOutDsvFl | kInDsvFl | kSymDsvFl | kOptArgDsvFl, "All notes off."},
  2562. { NULL, 0, 0, 0, 0 }
  2563. };
  2564. cmDspPicadae_t* p = cmDspInstAlloc(cmDspPicadae_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  2565. return &p->inst;
  2566. }
  2567. void _cmDspPicadaReset( cmDspCtx_t* ctx, cmDspInst_t* inst )
  2568. {
  2569. cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
  2570. memset(p->curDutyPctA,0,sizeof(p->curDutyPctA));
  2571. // send note-off messages to all keys
  2572. unsigned i = 0;
  2573. for(i=0; cmDspPicadaeVelMap[i].pitch !=0; ++i)
  2574. if( cmDspPicadaeVelMap[i].velMapA[0] != 0 )
  2575. {
  2576. _cmDspPicadaeSerialXmitNoteOff( ctx, inst, (uint8_t)cmDspPicadaeVelMap[i].pitch );
  2577. cmSleepMs(10);
  2578. }
  2579. // send pedal-up message
  2580. cmDspSetUInt(ctx,inst,kD0PcId, kSustainCtlMdId );
  2581. cmDspSetUInt(ctx,inst,kD0PcId, 0 );
  2582. cmDspSetUInt(ctx,inst,kStatusPcId,kCtlMdId);
  2583. }
  2584. cmDspRC_t _cmDspPicadaeReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2585. {
  2586. cmDspRC_t rc = kOkDspRC;
  2587. cmDspApplyAllDefaults(ctx,inst);
  2588. return rc;
  2589. }
  2590. cmDspRC_t _cmDspPicadaeRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2591. {
  2592. //cmDspPicadae_t* p = (cmDspPicadae_t*)inst;
  2593. switch( evt->dstVarId )
  2594. {
  2595. case kStatusPcId:
  2596. {
  2597. // note: the status byte arrives last (after d0 and d1)
  2598. unsigned status = cmDsvGetUInt(evt->valuePtr);
  2599. unsigned stat_no_ch = status & 0xf0;
  2600. // if this is a note-on or channel
  2601. if( stat_no_ch == kNoteOnMdId || stat_no_ch == kNoteOffMdId || stat_no_ch == kCtlMdId )
  2602. {
  2603. cmDspSetUInt(ctx,inst,kStatusPcId,stat_no_ch);
  2604. if( stat_no_ch == kNoteOnMdId || stat_no_ch == kNoteOffMdId )
  2605. _cmDspPicadaeSendNote( ctx, inst );
  2606. }
  2607. }
  2608. break;
  2609. case kAllOffPcId:
  2610. printf("Picadae All Off\n");
  2611. _cmDspPicadaReset( ctx, inst );
  2612. break;
  2613. default:
  2614. // store
  2615. cmDspSetEvent(ctx,inst,evt);
  2616. break;
  2617. }
  2618. return kOkDspRC;
  2619. }
  2620. cmDspClass_t* cmPicadaeClassCons( cmDspCtx_t* ctx )
  2621. {
  2622. cmDspClassSetup(&_cmPicadaeDC,ctx,"Picadae",
  2623. NULL,
  2624. _cmDspPicadaeAlloc,
  2625. NULL,
  2626. _cmDspPicadaeReset,
  2627. NULL,
  2628. _cmDspPicadaeRecv,
  2629. NULL,
  2630. NULL,
  2631. "Picadaesynth Mapper");
  2632. return &_cmPicadaeDC;
  2633. }
  2634. //------------------------------------------------------------------------------------------------------------
  2635. //)
  2636. //( { label:cmDspRecdPlay file_desc:"Record audio segments from a live perfromance and play them back at a later time" kw:[sunit gutim] }
  2637. enum
  2638. {
  2639. kChCntPrId,
  2640. kFnPrId,
  2641. kSecsPrId,
  2642. kMaxLaSecsPrId,
  2643. kCurLaSecsPrId,
  2644. kFadeRatePrId,
  2645. kScInitLocIdxPrId,
  2646. kScLocIdxPrId,
  2647. kCmdPrId,
  2648. kInAudioBasePrId
  2649. };
  2650. cmDspClass_t _cmRecdPlayDC;
  2651. typedef struct
  2652. {
  2653. cmDspInst_t inst;
  2654. cmRecdPlay* rcdply;
  2655. cmScH_t scH;
  2656. unsigned onSymId;
  2657. unsigned offSymId;
  2658. unsigned audioOutBaseId;
  2659. unsigned chCnt;
  2660. //unsigned scLocIdx;
  2661. } cmDspRecdPlay_t;
  2662. cmDspRC_t _cmDspRecdPlayParseRsrc( cmDspCtx_t* ctx, cmDspInst_t* inst, cmRecdPlay* rcdply )
  2663. {
  2664. cmDspRC_t rc = kOkDspRC;
  2665. const cmChar_t* path = NULL;
  2666. // read the 'recdplay' audio file path
  2667. if( cmDspRsrcString( ctx->dspH, &path, "recdPlayPath", NULL ) != kOkDspRC )
  2668. {
  2669. cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The 'recdPlayPath' resource string was not found.");
  2670. }
  2671. if( path == NULL )
  2672. path = "";
  2673. cmJsonH_t jsH = cmDspSysPgmRsrcHandle(ctx->dspH);
  2674. cmJsonNode_t* jnp = cmJsonFindValue(jsH,"recdPlay",NULL, kArrayTId);
  2675. if( jnp == NULL || cmJsonIsArray(jnp)==false )
  2676. {
  2677. // this is really a warning - the object does not require preloaded segments.
  2678. cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"Warning: The 'recdPlay' resource used to define pre-loaded segments was not found.");
  2679. return kOkDspRC;
  2680. }
  2681. unsigned n = cmJsonChildCount(jnp);
  2682. unsigned i;
  2683. // for each 'recdplay' segment record
  2684. for(i=0; i<n && rc==kOkDspRC; ++i)
  2685. {
  2686. cmJsonNode_t* cnp = cmJsonArrayElement(jnp,i);
  2687. const cmChar_t* label = NULL;
  2688. unsigned segSymId = cmInvalidId;
  2689. const cmChar_t* errLabel = NULL;
  2690. const cmChar_t* fn = NULL;
  2691. // read the ith segment record
  2692. if( cmJsonMemberValues(cnp,&errLabel,
  2693. "label", kStringTId, &label,
  2694. "file", kStringTId, &fn,
  2695. NULL) != kOkJsRC )
  2696. {
  2697. rc = cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The record at index %i in the 'recdPlay' pre-loaded segment list could not be parsed.",i);
  2698. goto errLabel;
  2699. }
  2700. // find or generate the symbol id for the segment label symbol
  2701. if((segSymId = cmSymTblRegisterSymbol(ctx->stH,label)) == cmInvalidId )
  2702. {
  2703. rc = cmDspInstErr(ctx,inst,kSymNotFoundDspRC,"The 'recdPlay' pre-load segment symbol '%s' could not be found or registered.",cmStringNullGuard(label));
  2704. goto errLabel;
  2705. }
  2706. // create the full path name for the segment audio file
  2707. if((fn = cmFsMakeFn( path, fn, NULL, NULL )) == NULL )
  2708. {
  2709. rc = cmDspInstErr(ctx,inst,kFileSysFailDspRC,"The 'recdPlay' file name '%s/%s' could not be generated.",cmStringNullGuard(path),cmStringNullGuard(fn));
  2710. goto errLabel;
  2711. }
  2712. // pre-load the segment
  2713. if( cmRecdPlayInsertRecord(rcdply,segSymId,fn) != cmOkRC )
  2714. rc = cmDspInstErr(ctx,inst,kSubSysFailDspRC,"The 'recdPlay' segment label:'%s' file:'%s' could not be loaded.",cmStringNullGuard(label),cmStringNullGuard(fn));
  2715. cmFsFreeFn(fn);
  2716. }
  2717. errLabel:
  2718. return rc;
  2719. }
  2720. cmDspRC_t _cmDspRecdPlayOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
  2721. {
  2722. cmDspRC_t rc =kOkDspRC;
  2723. const cmChar_t* fn;
  2724. cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
  2725. //p->scLocIdx = 0;
  2726. if((fn = cmDspStrcz(inst,kFnPrId)) == NULL || strlen(fn)==0 )
  2727. return cmDspInstErr(ctx,inst, kInvalidArgDspRC, "No score file name supplied.");
  2728. if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
  2729. return cmDspInstErr(ctx,inst, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
  2730. if( cmScoreIsValid(p->scH) )
  2731. {
  2732. unsigned i;
  2733. unsigned markerCnt = cmScoreMarkerLabelCount(p->scH);
  2734. double initFragSecs = cmDspDouble(inst,kSecsPrId);
  2735. double maxLaSecs = cmDspDouble(inst,kMaxLaSecsPrId);
  2736. double curLaSecs = cmDspDouble(inst,kCurLaSecsPrId);
  2737. printf("2 max la secs:%f\n",cmDspDouble(inst,kMaxLaSecsPrId));
  2738. if((p->rcdply = cmRecdPlayAlloc(ctx->cmProcCtx, NULL, cmDspSampleRate(ctx), markerCnt, p->chCnt, initFragSecs, maxLaSecs, curLaSecs)) == NULL)
  2739. return cmErrMsg(&inst->classPtr->err,kSubSysFailDspRC,"Unable to create the internal recorder-player object.");
  2740. for(i=0; i<markerCnt; ++i)
  2741. cmRecdPlayRegisterFrag(p->rcdply,i, cmScoreMarkerLabelSymbolId(p->scH,i ));
  2742. if((rc = _cmDspRecdPlayParseRsrc(ctx,inst,p->rcdply)) != kOkDspRC )
  2743. rc = cmDspInstErr(ctx,inst,kInstResetFailDspRC,"The 'recdplay' segment pre-load failed.");
  2744. //p->scLocIdx = cmDspUInt(inst,kScInitLocIdxPrId);
  2745. }
  2746. return rc;
  2747. }
  2748. cmDspInst_t* _cmDspRecdPlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  2749. {
  2750. if( va_cnt < 1 )
  2751. {
  2752. cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'RecdPlay' constructor must have a count of input ports.");
  2753. return NULL;
  2754. }
  2755. va_list vl1;
  2756. va_copy(vl1,vl);
  2757. int chCnt = va_arg(vl,int);
  2758. unsigned audioOutBase = kInAudioBasePrId + chCnt;
  2759. cmDspRecdPlay_t* p = cmDspInstAllocV(cmDspRecdPlay_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl1,
  2760. 1, "chs", kChCntPrId, 0,0, kUIntDsvFl | kReqArgDsvFl, "channel count.",
  2761. 1, "fn", kFnPrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." ,
  2762. 1, "secs", kSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "Initial fragment allocation in seconds.",
  2763. 1, "maxla", kMaxLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl | kReqArgDsvFl, "Maximum look-ahead buffer in seconds.",
  2764. 1, "curla", kCurLaSecsPrId, 0,0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Current look-head buffer in seconds.",
  2765. 1, "frate", kFadeRatePrId, 0,0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Fade rate in dB per second.",
  2766. 1, "initIdx",kScInitLocIdxPrId,0,0,kInDsvFl | kUIntDsvFl, "Score search start location.",
  2767. 1, "index", kScLocIdxPrId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower location index.",
  2768. 1, "cmd", kCmdPrId, 0,0, kInDsvFl | kSymDsvFl, "on=reset off=stop.",
  2769. chCnt, "in", kInAudioBasePrId,0,1, kInDsvFl | kAudioBufDsvFl, "Audio input",
  2770. chCnt, "out", audioOutBase, 0,1, kOutDsvFl | kAudioBufDsvFl, "Audio output",
  2771. 0 );
  2772. va_end(vl1);
  2773. p->onSymId = cmSymTblId(ctx->stH,"on");
  2774. p->offSymId = cmSymTblId(ctx->stH,"off");
  2775. p->audioOutBaseId = audioOutBase;
  2776. p->chCnt = chCnt;
  2777. //p->scLocIdx = 0;
  2778. printf("0 max la secs:%f\n",cmDspDouble(&p->inst,kMaxLaSecsPrId));
  2779. cmDspSetDefaultDouble(ctx,&p->inst, kSecsPrId, 0.0, 10.0 );
  2780. cmDspSetDefaultDouble(ctx,&p->inst, kMaxLaSecsPrId,0.0, 2.0);
  2781. cmDspSetDefaultDouble(ctx,&p->inst, kCurLaSecsPrId,0.0, 0.1);
  2782. cmDspSetDefaultDouble(ctx,&p->inst, kFadeRatePrId, 0.0, 1.0);
  2783. cmDspSetDefaultUInt( ctx,&p->inst, kScInitLocIdxPrId,0,0);
  2784. printf("1 max la secs:%f\n",cmDspDouble(&p->inst,kMaxLaSecsPrId));
  2785. return &p->inst;
  2786. }
  2787. cmDspRC_t _cmDspRecdPlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2788. {
  2789. cmDspRC_t rc = kOkDspRC;
  2790. cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
  2791. cmRecdPlayFree(&p->rcdply);
  2792. cmScoreFinalize(&p->scH);
  2793. return rc;
  2794. }
  2795. cmDspRC_t _cmDspRecdPlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2796. {
  2797. cmDspRC_t rc;
  2798. if((rc = _cmDspRecdPlayOpenScore(ctx,inst)) == kOkDspRC )
  2799. cmDspApplyAllDefaults(ctx,inst);
  2800. return rc;
  2801. }
  2802. cmDspRC_t _cmDspRecdPlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2803. {
  2804. cmDspRC_t rc = kOkDspRC;
  2805. cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
  2806. const cmSample_t* x[ p->chCnt ];
  2807. cmSample_t* y[ p->chCnt ];
  2808. unsigned n = 0;
  2809. unsigned i;
  2810. unsigned actChCnt = 0;
  2811. for(i=0; i<p->chCnt; ++i)
  2812. {
  2813. if( cmDspIsAudioInputConnected(ctx,inst,kInAudioBasePrId+i) == false )
  2814. {
  2815. x[i] = NULL;
  2816. y[i] = NULL;
  2817. }
  2818. else
  2819. {
  2820. if( i==0 )
  2821. n = cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0);
  2822. else
  2823. {
  2824. assert( n == cmDspAudioBufSmpCount(ctx,inst,kInAudioBasePrId+i,0));
  2825. }
  2826. x[i] = cmDspAudioBuf(ctx,inst,kInAudioBasePrId+i,0);
  2827. if( x[i] != NULL )
  2828. {
  2829. y[i] = cmDspAudioBuf(ctx,inst,p->audioOutBaseId+i,0);
  2830. if( y[i] != NULL )
  2831. {
  2832. assert( n == cmDspAudioBufSmpCount(ctx,inst,p->audioOutBaseId+i,0));
  2833. cmVOS_Zero(y[i],n);
  2834. actChCnt += 1;
  2835. }
  2836. }
  2837. }
  2838. }
  2839. cmRecdPlayExec(p->rcdply,x,y,actChCnt,n);
  2840. return rc;
  2841. }
  2842. cmDspRC_t _cmDspRecdPlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2843. {
  2844. cmDspRecdPlay_t* p = (cmDspRecdPlay_t*)inst;
  2845. if( p->rcdply == NULL )
  2846. return kOkDspRC;
  2847. cmDspSetEvent(ctx,inst,evt);
  2848. switch( evt->dstVarId )
  2849. {
  2850. case kCmdPrId:
  2851. if( cmDspSymbol(inst,kCmdPrId) == p->onSymId )
  2852. {
  2853. printf("rewind\n");
  2854. cmRecdPlayRewind(p->rcdply);
  2855. //p->scLocIdx = cmDspUInt(inst,kScInitLocIdxPrId);
  2856. }
  2857. else
  2858. if( cmDspSymbol(inst,kCmdPrId) == p->offSymId )
  2859. {
  2860. }
  2861. break;
  2862. case kCurLaSecsPrId:
  2863. cmRecdPlaySetLaSecs(p->rcdply, cmDspDouble(inst,kCurLaSecsPrId));
  2864. break;
  2865. case kScInitLocIdxPrId:
  2866. printf("init-idx:%i\n",cmDspUInt(inst,kScInitLocIdxPrId));
  2867. break;
  2868. case kScLocIdxPrId:
  2869. {
  2870. unsigned endScLocIdx = cmDspUInt(inst,kScLocIdxPrId);
  2871. if( endScLocIdx < cmDspUInt(inst,kScInitLocIdxPrId) )
  2872. break;
  2873. cmScoreLoc_t* loc = cmScoreLoc(p->scH, endScLocIdx );
  2874. if( loc == NULL )
  2875. break;
  2876. cmScoreMarker_t* mp = loc->markList;
  2877. for(; mp!=NULL; mp=mp->link)
  2878. switch( mp->markTypeId )
  2879. {
  2880. case kRecdBegScMId:
  2881. printf("recd-beg %s\n",cmSymTblLabel(ctx->stH,mp->labelSymId));
  2882. cmRecdPlayBeginRecord(p->rcdply, mp->labelSymId );
  2883. break;
  2884. case kRecdEndScMId:
  2885. printf("recd-end %s\n",cmSymTblLabel(ctx->stH,mp->labelSymId));
  2886. cmRecdPlayEndRecord(p->rcdply, mp->labelSymId );
  2887. break;
  2888. case kPlayBegScMId:
  2889. printf("play-beg\n");
  2890. cmRecdPlayBeginPlay(p->rcdply, mp->labelSymId );
  2891. break;
  2892. case kPlayEndScMId:
  2893. printf("play-end\n");
  2894. cmRecdPlayEndPlay(p->rcdply, mp->labelSymId );
  2895. break;
  2896. case kFadeScMId:
  2897. printf("fade-beg\n");
  2898. cmRecdPlayBeginFade(p->rcdply, mp->labelSymId, cmDspDouble(inst,kFadeRatePrId) );
  2899. break;
  2900. default:
  2901. break;
  2902. }
  2903. //p->scLocIdx = endScLocIdx+1;
  2904. }
  2905. break;
  2906. }
  2907. return kOkDspRC;
  2908. }
  2909. cmDspClass_t* cmRecdPlayClassCons( cmDspCtx_t* ctx )
  2910. {
  2911. cmDspClassSetup(&_cmRecdPlayDC,ctx,"RecdPlay",
  2912. NULL,
  2913. _cmDspRecdPlayAlloc,
  2914. _cmDspRecdPlayFree,
  2915. _cmDspRecdPlayReset,
  2916. _cmDspRecdPlayExec,
  2917. _cmDspRecdPlayRecv,
  2918. NULL,
  2919. NULL,
  2920. "Score controlled live recorder/player");
  2921. return &_cmRecdPlayDC;
  2922. }
  2923. //------------------------------------------------------------------------------------------------------------
  2924. //)
  2925. //( { label:cmDspGoertzel file_desc:"Goertzel tone detection filter" kw:[sunit gutim] }
  2926. enum
  2927. {
  2928. kHopFactGrId,
  2929. kInGrId,
  2930. kHzBaseGrId,
  2931. };
  2932. cmDspClass_t _cmGoertzelDC;
  2933. typedef struct
  2934. {
  2935. cmDspInst_t inst;
  2936. cmGoertzel* g;
  2937. double outPhs;
  2938. unsigned outBaseGrId;
  2939. unsigned chCnt;
  2940. } cmDspGoertzel_t;
  2941. cmDspInst_t* _cmDspGoertzelAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  2942. {
  2943. if( va_cnt !=3 )
  2944. {
  2945. cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'Goertzel' constructor must have two arguments: a channel count and frequency array.");
  2946. return NULL;
  2947. }
  2948. va_list vl1;
  2949. va_copy(vl1,vl);
  2950. unsigned hopFact = va_arg(vl,unsigned);
  2951. int chCnt = va_arg(vl,int);
  2952. double* hzV = va_arg(vl,double*);
  2953. unsigned outBaseGrId = kHzBaseGrId + chCnt;
  2954. unsigned i;
  2955. cmDspGoertzel_t* p = cmDspInstAllocV(cmDspGoertzel_t,ctx,classPtr,instSymId,id,storeSymId,1,vl1,
  2956. 1, "hop", kHopFactGrId, 0,0, kInDsvFl | kDoubleDsvFl, "Hop factor",
  2957. 1, "in", kInGrId, 0,1, kInDsvFl | kAudioBufDsvFl, "Audio input",
  2958. chCnt, "hz", kHzBaseGrId, 0,0, kInDsvFl | kDoubleDsvFl, "Hz input.",
  2959. chCnt, "out", outBaseGrId, 0,1, kOutDsvFl | kDoubleDsvFl, "Detector output",
  2960. 0 );
  2961. va_end(vl1);
  2962. p->outBaseGrId = outBaseGrId;
  2963. p->chCnt = chCnt;
  2964. p->g = cmGoertzelAlloc(ctx->cmProcCtx, NULL, 0, NULL, 0,0,0,0 );
  2965. cmDspSetDefaultUInt(ctx,&p->inst, kHopFactGrId, 0, cmMax(hopFact,1));
  2966. for(i=0; i<chCnt; ++i)
  2967. cmDspSetDefaultDouble(ctx,&p->inst, kHzBaseGrId+i, 0.0, hzV[i] );
  2968. return &p->inst;
  2969. }
  2970. cmDspRC_t _cmDspGoertzelSetup( cmDspCtx_t* ctx, cmDspInst_t* inst )
  2971. {
  2972. cmDspRC_t rc = kOkDspRC;
  2973. cmDspGoertzel_t* p = (cmDspGoertzel_t*)inst;
  2974. unsigned hopFact = cmDspUInt(inst,kHopFactGrId);
  2975. unsigned procSmpCnt = cmDspAudioBufSmpCount(ctx,inst,kInGrId,0);
  2976. unsigned wndSmpCnt = procSmpCnt * hopFact;
  2977. double fcHzV[ p->chCnt ];
  2978. unsigned i;
  2979. for(i=0; i<p->chCnt; ++i)
  2980. {
  2981. double hz;
  2982. if( p->g->ch == NULL || p->g->ch[i].hz == 0 )
  2983. hz = cmDspDouble(inst,kHzBaseGrId);
  2984. else
  2985. hz = p->g->ch[i].hz;
  2986. fcHzV[i] = hz;
  2987. }
  2988. if( cmGoertzelInit(p->g,cmDspSysSampleRate(ctx->dspH),fcHzV,p->chCnt,procSmpCnt,procSmpCnt,wndSmpCnt) != cmOkRC )
  2989. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to initialize the internal Goertzel detector.");
  2990. return rc;
  2991. }
  2992. cmDspRC_t _cmDspGoertzelFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  2993. {
  2994. cmDspRC_t rc = kOkDspRC;
  2995. cmDspGoertzel_t* p = (cmDspGoertzel_t*)inst;
  2996. cmGoertzelFree(&p->g);
  2997. return rc;
  2998. }
  2999. cmDspRC_t _cmDspGoertzelReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3000. {
  3001. cmDspGoertzel_t* p = (cmDspGoertzel_t*)inst;
  3002. cmDspApplyAllDefaults(ctx,inst);
  3003. p->outPhs = 0;
  3004. return _cmDspGoertzelSetup(ctx, inst );
  3005. }
  3006. cmDspRC_t _cmDspGoertzelExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3007. {
  3008. cmDspRC_t rc = kOkDspRC;
  3009. cmDspGoertzel_t* p = (cmDspGoertzel_t*)inst;
  3010. const cmSample_t* x = cmDspAudioBuf(ctx,inst,kInGrId,0);
  3011. unsigned n = cmDspAudioBufSmpCount(ctx,inst,kInGrId,0);
  3012. double outMs = 50.0;
  3013. double outPhsMax = outMs * cmDspSysSampleRate(ctx->dspH) / 1000.0;
  3014. double outV[ p->chCnt ];
  3015. unsigned i;
  3016. if( x != NULL )
  3017. {
  3018. cmGoertzelExec(p->g,x,n,outV,p->chCnt);
  3019. p->outPhs += n;
  3020. if( p->outPhs > outPhsMax )
  3021. {
  3022. while( p->outPhs > outPhsMax )
  3023. p->outPhs -= outPhsMax;
  3024. for(i=0; i<p->chCnt; ++i)
  3025. {
  3026. cmDspSetDouble(ctx,inst,p->outBaseGrId+i,outV[i]);
  3027. //printf("%f ",outV[i]);
  3028. }
  3029. //printf("\n");
  3030. }
  3031. }
  3032. return rc;
  3033. }
  3034. cmDspRC_t _cmDspGoertzelRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3035. {
  3036. cmDspGoertzel_t* p = (cmDspGoertzel_t*)inst;
  3037. cmDspSetEvent(ctx,inst,evt);
  3038. if( kHzBaseGrId <= evt->dstVarId && evt->dstVarId < kHzBaseGrId+p->chCnt )
  3039. cmGoertzelSetFcHz(p->g, evt->dstVarId - kHzBaseGrId, cmDspDouble(inst,evt->dstVarId));
  3040. else
  3041. {
  3042. if( evt->dstVarId==kHopFactGrId )
  3043. {
  3044. _cmDspGoertzelSetup(ctx,inst);
  3045. }
  3046. }
  3047. return kOkDspRC;
  3048. }
  3049. cmDspClass_t* cmGoertzelClassCons( cmDspCtx_t* ctx )
  3050. {
  3051. cmDspClassSetup(&_cmGoertzelDC,ctx,"Goertzel",
  3052. NULL,
  3053. _cmDspGoertzelAlloc,
  3054. _cmDspGoertzelFree,
  3055. _cmDspGoertzelReset,
  3056. _cmDspGoertzelExec,
  3057. _cmDspGoertzelRecv,
  3058. NULL,
  3059. NULL,
  3060. "Goertzel Tone Detector Filter");
  3061. return &_cmGoertzelDC;
  3062. }
  3063. //------------------------------------------------------------------------------------------------------------
  3064. //)
  3065. //( { label:cmDspSyncRecd file_desc:"Time align a MIDI and associated audio recording" kw:[sunit gutim] }
  3066. enum
  3067. {
  3068. kRecdDirSrId,
  3069. kSrFnSrId,
  3070. kAfSrId,
  3071. kBitsSrId,
  3072. kCmdSrId,
  3073. kStatusSrId,
  3074. kD0SrId,
  3075. kD1SrId,
  3076. kSecSrId,
  3077. kNSecSrId,
  3078. kAinBaseSrId
  3079. };
  3080. cmDspClass_t _cmSyncRecdDC;
  3081. typedef struct
  3082. {
  3083. cmDspInst_t inst;
  3084. unsigned chCnt;
  3085. cmTimeSpec_t ats;
  3086. cmSyncRecdH_t srH;
  3087. unsigned openSymId;
  3088. unsigned closeSymId;
  3089. const cmChar_t* aFn;
  3090. const cmChar_t* srFn;
  3091. unsigned smpIdx;
  3092. } cmDspSyncRecd_t;
  3093. cmDspRC_t _cmDspSyncRecdCreateFile( cmDspCtx_t* ctx, cmDspInst_t* inst )
  3094. {
  3095. cmDspSyncRecd_t* p = (cmDspSyncRecd_t*)inst;
  3096. const cmChar_t* aFn = cmDspStrcz(inst,kAfSrId);
  3097. const cmChar_t* srFn = cmDspStrcz(inst,kSrFnSrId);
  3098. const cmChar_t* dir = cmDspStrcz(inst,kRecdDirSrId);
  3099. if( !cmFsIsDir(dir) )
  3100. return cmDspInstErr(ctx,&p->inst,kInvalidArgDspRC,"'%s' is not a valid directory.",cmStringNullGuard(dir));
  3101. cmMemPtrFree(&p->aFn);
  3102. if( cmFsGenFn(dir,aFn,"aiff",&p->aFn) != kOkFsRC )
  3103. return cmDspInstErr(ctx,&p->inst,kFileSysFailDspRC,"Audio file name generation failed for dir='%s' and prefix='%s'.",cmStringNullGuard(dir),cmStringNullGuard(aFn));
  3104. cmMemPtrFree(&p->srFn);
  3105. if( cmFsGenFn(dir,srFn,"sr",&p->srFn) != kOkFsRC )
  3106. return cmDspInstErr(ctx,&p->inst,kFileSysFailDspRC,"Sync-recd file name generation failed for dir='%s' and prefix='%s'.",cmStringNullGuard(dir),cmStringNullGuard(srFn));
  3107. unsigned bits = cmDspUInt(inst,kBitsSrId);
  3108. if( cmSyncRecdCreate( ctx->cmCtx, &p->srH, p->srFn, p->aFn, cmDspSampleRate(ctx), p->chCnt, bits ) != kOkSyRC )
  3109. return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd file create failed for '%s'.",p->srFn);
  3110. p->smpIdx = 0;
  3111. return kOkDspRC;
  3112. }
  3113. cmDspInst_t* _cmDspSyncRecdAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  3114. {
  3115. cmDspSyncRecd_t* p = cmDspInstAllocV(cmDspSyncRecd_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl,
  3116. 1, "dir", kRecdDirSrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Recording directory.",
  3117. 1, "srfn", kSrFnSrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "SyncRecd file prefix.",
  3118. 1, "afn", kAfSrId, 0,0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Audio file prefix.",
  3119. 1, "bits", kBitsSrId, 0,0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Audio file bits per sample.",
  3120. 1, "cmd", kCmdSrId, 0,0, kInDsvFl | kSymDsvFl, "Command: open | close",
  3121. 1, "status", kStatusSrId, 0,0, kInDsvFl | kUIntDsvFl, "MIDI status",
  3122. 1, "d0", kD0SrId, 0,0, kInDsvFl | kUIntDsvFl, "MIDI d0",
  3123. 1, "d1", kD1SrId, 0,0, kInDsvFl | kUIntDsvFl, "MIDI d1",
  3124. 1, "sec", kSecSrId, 0,0, kInDsvFl | kUIntDsvFl, "MIDI Timestamp Seconds",
  3125. 1, "nsec", kNSecSrId, 0,0, kInDsvFl | kUIntDsvFl, "MIDI Timestamp Nanoseconds",
  3126. 2, "ain", kAinBaseSrId, 0,1, kInDsvFl | kAudioBufDsvFl, "Audio Input",
  3127. 0 );
  3128. p->chCnt = 2;
  3129. p->openSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"open");
  3130. p->closeSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"close");
  3131. cmDspSetDefaultUInt(ctx,&p->inst,kBitsSrId,0,16);
  3132. return &p->inst;
  3133. }
  3134. cmDspRC_t _cmDspSyncRecdFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3135. {
  3136. cmDspRC_t rc = kOkDspRC;
  3137. cmDspSyncRecd_t* p = (cmDspSyncRecd_t*)inst;
  3138. cmMemPtrFree(&p->aFn);
  3139. cmMemPtrFree(&p->srFn);
  3140. cmSyncRecdFinal(&p->srH);
  3141. return rc;
  3142. }
  3143. cmDspRC_t _cmDspSyncRecdReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3144. {
  3145. cmDspRC_t rc = kOkDspRC;
  3146. cmDspApplyAllDefaults(ctx,inst);
  3147. return rc;
  3148. }
  3149. cmDspRC_t _cmDspSyncRecdExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3150. {
  3151. cmDspRC_t rc = kOkDspRC;
  3152. cmDspSyncRecd_t* p = (cmDspSyncRecd_t*)inst;
  3153. const cmSample_t* x[ p->chCnt ];
  3154. unsigned n = 0;
  3155. unsigned i;
  3156. //const cmTimeSpec_t* ts = &ctx->ctx->oTimeStamp;
  3157. //printf("SR: %ld %ld\n",ts->tv_sec,ts->tv_nsec);
  3158. p->ats = ctx->ctx->iTimeStamp;
  3159. for(i=0; i<p->chCnt; ++i)
  3160. {
  3161. if( i==0 )
  3162. n = cmDspAudioBufSmpCount(ctx,inst,kAinBaseSrId+i,0);
  3163. else
  3164. { assert( n == cmDspAudioBufSmpCount(ctx,inst,kAinBaseSrId+i,0)); }
  3165. x[i] = cmDspAudioBuf(ctx,inst,kAinBaseSrId+i,0);
  3166. }
  3167. if( n>0 && cmSyncRecdIsValid(p->srH ) )
  3168. if( cmSyncRecdAudioWrite( p->srH, &ctx->ctx->iTimeStamp, p->smpIdx, x, p->chCnt, n ) != kOkSyRC )
  3169. return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd audio update failed.");
  3170. p->smpIdx += n;
  3171. return rc;
  3172. }
  3173. cmDspRC_t _cmDspSyncRecdRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3174. {
  3175. cmDspRC_t rc = kOkDspRC;
  3176. cmDspSyncRecd_t* p = (cmDspSyncRecd_t*)inst;
  3177. cmDspSetEvent(ctx,inst,evt);
  3178. switch( evt->dstVarId )
  3179. {
  3180. case kStatusSrId:
  3181. if(cmMidiIsChStatus( cmDspUInt(inst,kStatusSrId) ) )
  3182. {
  3183. cmTimeSpec_t ts;
  3184. ts.tv_sec = cmDspUInt(inst,kSecSrId);
  3185. ts.tv_nsec = cmDspUInt(inst,kNSecSrId);
  3186. //printf("%i %i\n",cmDspUInt(inst,kD1SrId),cmTimeElapsedMicros(&ts,&p->ats));
  3187. if( cmSyncRecdIsValid(p->srH ) )
  3188. if( cmSyncRecdMidiWrite(p->srH, &ts, cmDspUInt(inst,kStatusSrId), cmDspUInt(inst,kD0SrId), cmDspUInt(inst,kD1SrId) ) != kOkSyRC )
  3189. return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Sync-recd MIDI update failed.");
  3190. }
  3191. break;
  3192. case kCmdSrId:
  3193. {
  3194. unsigned cmdId = cmDspSymbol(inst,kCmdSrId);
  3195. if( cmdId == p->openSymId )
  3196. rc = _cmDspSyncRecdCreateFile(ctx,inst);
  3197. else
  3198. if( cmdId == p->closeSymId && cmSyncRecdIsValid(p->srH))
  3199. {
  3200. cmSyncRecdFinal(&p->srH);
  3201. //cmSyncRecdTest(ctx->cmCtx);
  3202. }
  3203. }
  3204. break;
  3205. }
  3206. return rc;
  3207. }
  3208. cmDspClass_t* cmSyncRecdClassCons( cmDspCtx_t* ctx )
  3209. {
  3210. cmDspClassSetup(&_cmSyncRecdDC,ctx,"SyncRecd",
  3211. NULL,
  3212. _cmDspSyncRecdAlloc,
  3213. _cmDspSyncRecdFree,
  3214. _cmDspSyncRecdReset,
  3215. _cmDspSyncRecdExec,
  3216. _cmDspSyncRecdRecv,
  3217. NULL,
  3218. NULL,
  3219. "Synchronized Audio and MIDI recorder.");
  3220. return &_cmSyncRecdDC;
  3221. }
  3222. //------------------------------------------------------------------------------------------------------------
  3223. //)
  3224. //( { label:cmDspTakeSeqBldr file_desc:"User interface unit for creating a single sequence from multiple, score aligned, MIDI fragments." kw:[sunit gutim] }
  3225. enum
  3226. {
  3227. kFnTsbId,
  3228. kBldrTsbId,
  3229. kSelTsbId,
  3230. kRefreshTsbId,
  3231. kSendTsbId
  3232. };
  3233. cmDspClass_t _cmTakeSeqBldrDC;
  3234. typedef struct
  3235. {
  3236. cmDspInst_t inst;
  3237. cmTakeSeqBldrH_t h;
  3238. bool errFl;
  3239. } cmDspTakeSeqBldr_t;
  3240. cmDspInst_t* _cmDspTakeSeqBldrAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  3241. {
  3242. cmDspTakeSeqBldr_t* p = cmDspInstAllocV(cmDspTakeSeqBldr_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl,
  3243. 1, "fn", kFnTsbId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score Tracking file.",
  3244. 1, "bldr", kBldrTsbId, 0, 0, kOutDsvFl | kPtrDsvFl, "Bldr Ref",
  3245. 1, "sel", kSelTsbId, 0, 0, kOutDsvFl | kUIntDsvFl, "Selected score element location index.",
  3246. 1, "refresh",kRefreshTsbId, 0, 0, kOutDsvFl | kUIntDsvFl, "Refresh",
  3247. 1, "send", kSendTsbId, 0, 0, kInDsvFl | kTypeDsvMask, "Resend last selected score element location.",
  3248. 0 );
  3249. p->errFl = false;
  3250. cmDspSetDefaultInt( ctx, &p->inst, kRefreshTsbId, 0, 0);
  3251. if( cmTakeSeqBldrAlloc(ctx->cmCtx, &p->h ) != kOkTsbRC )
  3252. cmErrMsg(&p->inst.classPtr->err, kSubSysFailDspRC, "Allocate TaskSeqBldr object.");
  3253. else
  3254. {
  3255. cmDspUiTakeSeqBldrCreate(ctx,&p->inst,kFnTsbId,kBldrTsbId,kSelTsbId,kRefreshTsbId);
  3256. }
  3257. return &p->inst;
  3258. }
  3259. cmDspRC_t _cmDspTakeSeqBldrSetup( cmDspCtx_t* ctx, cmDspInst_t* inst )
  3260. {
  3261. cmDspRC_t rc = kOkDspRC;
  3262. cmDspTakeSeqBldr_t* p = (cmDspTakeSeqBldr_t*)inst;
  3263. if( cmTakeSeqBldrInitialize(p->h, cmDspStrcz(inst,kFnTsbId) ) != kOkTsbRC )
  3264. {
  3265. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to initialize the internal TakeSeqBldr object with %s.",cmStringNullGuard(cmDspStrcz(inst,kFnTsbId)));
  3266. }
  3267. else
  3268. {
  3269. cmDspSetPtr(ctx,inst,kBldrTsbId,p->h.h);
  3270. p->errFl = false;
  3271. }
  3272. return rc;
  3273. }
  3274. cmDspRC_t _cmDspTakeSeqBldrFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3275. {
  3276. cmDspRC_t rc = kOkDspRC;
  3277. cmDspTakeSeqBldr_t* p = (cmDspTakeSeqBldr_t*)inst;
  3278. cmTakeSeqBldrFree(&p->h);
  3279. return rc;
  3280. }
  3281. cmDspRC_t _cmDspTakeSeqBldrReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3282. {
  3283. //cmDspTakeSeqBldr_t* p = (cmDspTakeSeqBldr_t*)inst;
  3284. cmDspApplyAllDefaults(ctx,inst);
  3285. return _cmDspTakeSeqBldrSetup(ctx, inst );
  3286. }
  3287. cmDspRC_t _cmDspTakeSeqBldrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3288. {
  3289. cmDspRC_t rc = kOkDspRC;
  3290. return rc;
  3291. }
  3292. cmDspRC_t _cmDspTakeSeqBldrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3293. {
  3294. // not matter what arrives at the 'send' input ....
  3295. if( evt->dstVarId == kSendTsbId )
  3296. {
  3297. // send the last score loc
  3298. unsigned selIdx;
  3299. if((selIdx = cmDspUInt(inst,kSelTsbId)) != cmInvalidIdx )
  3300. cmDspSetUInt(ctx,inst,kSelTsbId, selIdx );
  3301. return kOkDspRC;
  3302. }
  3303. cmDspSetEvent(ctx,inst,evt);
  3304. switch(evt->dstVarId)
  3305. {
  3306. case kFnTsbId:
  3307. _cmDspMidiFilePlayOpen(ctx, inst );
  3308. break;
  3309. }
  3310. return kOkDspRC;
  3311. }
  3312. cmDspClass_t* cmTakeSeqBldrClassCons( cmDspCtx_t* ctx )
  3313. {
  3314. cmDspClassSetup(&_cmTakeSeqBldrDC,ctx,"TakeSeqBldr",
  3315. NULL,
  3316. _cmDspTakeSeqBldrAlloc,
  3317. _cmDspTakeSeqBldrFree,
  3318. _cmDspTakeSeqBldrReset,
  3319. _cmDspTakeSeqBldrExec,
  3320. _cmDspTakeSeqBldrRecv,
  3321. NULL,
  3322. NULL,
  3323. "TakeSeqBldr");
  3324. return &_cmTakeSeqBldrDC;
  3325. }
  3326. //------------------------------------------------------------------------------------------------------------
  3327. //)
  3328. //( { label:cmDspTakeSeqRend file_desc:"User interface unit for graphically rendering the MIDI sequences created by cmDspTakeSeqBldr." kw:[sunit gutim] }
  3329. enum
  3330. {
  3331. kBldrTsrId,
  3332. kRefreshTsrId,
  3333. kCmdTsrId,
  3334. kSelTsrId,
  3335. kStatusTsrId,
  3336. kD0TsrId,
  3337. kD1TsrId,
  3338. kSmpIdxTsrId
  3339. };
  3340. cmDspClass_t _cmTakeSeqRendDC;
  3341. typedef struct
  3342. {
  3343. cmDspInst_t inst;
  3344. cmTakeSeqBldrH_t h;
  3345. unsigned startSymId;
  3346. unsigned stopSymId;
  3347. unsigned contSymId;
  3348. unsigned onSymId;
  3349. unsigned offSymId;
  3350. bool errFl;
  3351. } cmDspTakeSeqRend_t;
  3352. cmDspInst_t* _cmDspTakeSeqRendAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  3353. {
  3354. cmDspTakeSeqRend_t* p = cmDspInstAllocV(cmDspTakeSeqRend_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl,
  3355. 1, "bldr", kBldrTsrId, 0, 0, kInDsvFl | kPtrDsvFl | kOptArgDsvFl, "Take Sequene Builder Ref",
  3356. 1, "refresh",kRefreshTsrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Refresh",
  3357. 1, "cmd", kCmdTsrId, 0, 0, kInDsvFl | kSymDsvFl, "start | stop | continue" ,
  3358. 1, "sel", kSelTsrId, 0, 0, kInDsvFl | kUIntDsvFl, "Selected score element location index input.",
  3359. 1, "status", kStatusTsrId, 0, 0, kOutDsvFl | kIntDsvFl, "Status value output",
  3360. 1, "d0", kD0TsrId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 0" ,
  3361. 1, "d1", kD1TsrId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 1",
  3362. 1, "smpidx", kSmpIdxTsrId, 0, 0, kOutDsvFl | kUIntDsvFl, "Msg time tag as a sample index.",
  3363. 0 );
  3364. p->startSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"start");
  3365. p->stopSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"stop");
  3366. p->contSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"continue");
  3367. p->onSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"on");
  3368. p->offSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"off");
  3369. p->errFl = false;
  3370. cmDspSetDefaultInt( ctx, &p->inst, kRefreshTsrId, 0, 0);
  3371. cmDspSetDefaultSymbol(ctx, &p->inst, kCmdTsrId, p->stopSymId);
  3372. cmDspSetDefaultInt( ctx, &p->inst, kSmpIdxTsrId, 0, 0);
  3373. cmDspSetDefaultUInt( ctx, &p->inst, kStatusTsrId, 0, 0);
  3374. cmDspSetDefaultUInt( ctx, &p->inst, kD0TsrId, 0, 0);
  3375. cmDspSetDefaultUInt( ctx, &p->inst, kD1TsrId, 0, 0);
  3376. cmDspUiTakeSeqRendCreate(ctx,&p->inst,kBldrTsrId,kRefreshTsrId,kSelTsrId);
  3377. return &p->inst;
  3378. }
  3379. cmDspRC_t _cmDspTakeSeqRendFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3380. {
  3381. cmDspRC_t rc = kOkDspRC;
  3382. return rc;
  3383. }
  3384. cmDspRC_t _cmDspTakeSeqRendReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3385. {
  3386. //cmDspTakeSeqRend_t* p = (cmDspTakeSeqRend_t*)inst;
  3387. cmDspApplyAllDefaults(ctx,inst);
  3388. return kOkDspRC;
  3389. }
  3390. typedef struct
  3391. {
  3392. cmDspCtx_t* ctx;
  3393. cmDspInst_t* inst;
  3394. } _cmDspTakeSeqRendCbArg_t;
  3395. // Called from cmDspTakeSeqRendExec() -> cmTakeSeqRendPlayExec() to
  3396. // deliver MIDI messages which need to be transmitted.
  3397. void _cmDspTakeSeqRendMidiCb( void* arg, const cmTksbEvent_t* e )
  3398. {
  3399. _cmDspTakeSeqRendCbArg_t* a = (_cmDspTakeSeqRendCbArg_t*)arg;
  3400. switch( e->status )
  3401. {
  3402. case kNoteOffMdId:
  3403. case kNoteOnMdId:
  3404. case kCtlMdId:
  3405. //if( !cmMidiIsPedal(e->status,e->d0))
  3406. {
  3407. cmDspSetUInt(a->ctx,a->inst, kSmpIdxTsrId, e->smpIdx);
  3408. cmDspSetUInt(a->ctx,a->inst, kD1TsrId, e->d1);
  3409. cmDspSetUInt(a->ctx,a->inst, kD0TsrId, e->d0);
  3410. cmDspSetUInt(a->ctx,a->inst, kStatusTsrId, e->status);
  3411. }
  3412. break;
  3413. }
  3414. }
  3415. void _cmDspTakeSeqRendPedalsUp( cmDspCtx_t* ctx, cmDspInst_t* inst )
  3416. {
  3417. _cmDspTakeSeqRendCbArg_t a;
  3418. a.ctx = ctx;
  3419. a.inst = inst;
  3420. cmTksbEvent_t e[] =
  3421. {
  3422. { 0, kCtlMdId, kSustainCtlMdId, 0 },
  3423. { 0, kCtlMdId, kPortamentoCtlMdId,0 },
  3424. { 0, kCtlMdId, kSostenutoCtlMdId, 0 },
  3425. { 0, kCtlMdId, kSoftPedalCtlMdId, 0 },
  3426. { 0, kCtlMdId, kLegatoCtlMdId, 0 }
  3427. };
  3428. unsigned n = sizeof(e)/sizeof(e[0]);
  3429. unsigned i;
  3430. for(i=0; i<n; ++i)
  3431. _cmDspTakeSeqRendMidiCb(&a,e+i);
  3432. }
  3433. cmDspRC_t _cmDspTakeSeqRendExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3434. {
  3435. cmDspRC_t rc = kOkDspRC;
  3436. cmDspTakeSeqRend_t* p = (cmDspTakeSeqRend_t*)inst;
  3437. if( cmDspSymbol(inst,kCmdTsrId) != p->stopSymId )
  3438. {
  3439. if( cmTakeSeqBldrIsValid(p->h) == false )
  3440. {
  3441. if( p->errFl==false )
  3442. {
  3443. rc = cmErrMsg(&inst->classPtr->err, kInvalidStateDspRC,"The Take Sequence Builder not been given a valid file.");
  3444. p->errFl = true;
  3445. }
  3446. return rc;
  3447. }
  3448. unsigned sPc = cmDspSamplesPerCycle(ctx);
  3449. _cmDspTakeSeqRendCbArg_t arg;
  3450. arg.inst = inst;
  3451. arg.ctx = ctx;
  3452. // This call may result in multiple callbacks
  3453. // to _cmDspTakeSeqRendMidiCb() from within the function.
  3454. cmTakeSeqBldrPlayExec(p->h,sPc,_cmDspTakeSeqRendMidiCb, &arg );
  3455. }
  3456. return rc;
  3457. }
  3458. cmDspRC_t _cmDspTakeSeqRendRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3459. {
  3460. cmDspTakeSeqRend_t* p = (cmDspTakeSeqRend_t*)inst;
  3461. printf("Recv:%s\n",cmStringNullGuard(cmDspVarLabel(ctx, inst, evt->dstVarId)) );
  3462. cmDspSetEvent(ctx,inst,evt);
  3463. switch(evt->dstVarId)
  3464. {
  3465. case kBldrTsrId:
  3466. p->h.h = cmDspPtr(inst,kBldrTsrId);
  3467. break;
  3468. case kCmdTsrId:
  3469. {
  3470. unsigned symId = cmDspSymbol(inst,kCmdTsrId);
  3471. if( symId == p->onSymId )
  3472. cmDspSetSymbol( ctx, inst, kCmdTsrId, p->startSymId );
  3473. else
  3474. if( symId == p->offSymId )
  3475. cmDspSetSymbol( ctx, inst, kCmdTsrId, p->stopSymId );
  3476. if( cmTakeSeqBldrIsValid(p->h) && cmDspSymbol(inst,kCmdTsrId)==p->startSymId )
  3477. {
  3478. _cmDspTakeSeqRendPedalsUp( ctx, inst );
  3479. cmTakeSeqBldrPlaySeekLoc(p->h, cmInvalidId );
  3480. }
  3481. }
  3482. break;
  3483. case kSelTsrId:
  3484. {
  3485. // seek the playback position to the scLocIdx.
  3486. unsigned scLocIdx = cmDspUInt(inst,kSelTsrId);
  3487. if( cmTakeSeqBldrIsValid(p->h) && cmTakeSeqBldrPlaySeekLoc(p->h, scLocIdx ) != kOkTsbRC )
  3488. return cmDspInstErr(ctx,&p->inst,kSubSysFailDspRC,"Take Sequence Bldr Seek failed on score location index %i.", scLocIdx);
  3489. }
  3490. break;
  3491. }
  3492. return kOkDspRC;
  3493. }
  3494. cmDspClass_t* cmTakeSeqRendClassCons( cmDspCtx_t* ctx )
  3495. {
  3496. cmDspClassSetup(&_cmTakeSeqRendDC,ctx,"TakeSeqRend",
  3497. NULL,
  3498. _cmDspTakeSeqRendAlloc,
  3499. _cmDspTakeSeqRendFree,
  3500. _cmDspTakeSeqRendReset,
  3501. _cmDspTakeSeqRendExec,
  3502. _cmDspTakeSeqRendRecv,
  3503. NULL,
  3504. NULL,
  3505. "TakeSeqRend");
  3506. return &_cmTakeSeqRendDC;
  3507. }
  3508. //------------------------------------------------------------------------------------------------------------
  3509. //)
  3510. //( { label:cmDspReflectCalc file_desc:"Estimate the time-of-flight of from an acoustic signal from a speaker to a microphone." kw:[sunit gutim] }
  3511. enum
  3512. {
  3513. kLfsrN_RcId,
  3514. kMlsCoeff0RcId,
  3515. kMlsCoeff1RcId,
  3516. kSmpPerChipRcId,
  3517. kRcosBetaRcId,
  3518. kRcosOS_RcId,
  3519. kCarrierHzRcId,
  3520. kAtkDcyMsRcId,
  3521. kPhatAlphaRcId,
  3522. kPhatMultRcId,
  3523. kInRcId,
  3524. kOutRcId,
  3525. };
  3526. cmDspClass_t _cmReflectCalcDC;
  3527. typedef struct
  3528. {
  3529. cmDspInst_t inst;
  3530. cmReflectCalc_t* r;
  3531. } cmDspReflectCalc_t;
  3532. cmDspInst_t* _cmDspReflectCalcAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  3533. {
  3534. // if( va_cnt !=3 )
  3535. // {
  3536. // cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'ReflectCalc' constructor must have two arguments: a channel count and frequency array.");
  3537. // return NULL;
  3538. // }
  3539. cmDspReflectCalc_t* p = cmDspInstAllocV(cmDspReflectCalc_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl,
  3540. 1, "lfsrN", kLfsrN_RcId, 0,0, kInDsvFl | kUIntDsvFl, "Gold code generator LFSR length",
  3541. 1, "mlsc0", kMlsCoeff0RcId, 0,0, kInDsvFl | kUIntDsvFl, "LFSR coefficient 0",
  3542. 1, "mlsc1", kMlsCoeff1RcId, 0,0, kInDsvFl | kUIntDsvFl, "LFSR coefficient 0",
  3543. 1, "spchip",kSmpPerChipRcId,0,0, kInDsvFl | kUIntDsvFl, "Samples per spreading code bit.",
  3544. 1, "rcosb", kRcosBetaRcId, 0,0, kInDsvFl | kDoubleDsvFl, "Raised cosine beta",
  3545. 1, "rcosos",kRcosOS_RcId, 0,0, kInDsvFl | kUIntDsvFl, "Raised cosine oversample factor.",
  3546. 1, "carhz", kCarrierHzRcId, 0,0, kInDsvFl | kDoubleDsvFl, "Carrier frequency in Hertz.",
  3547. 1, "envms", kAtkDcyMsRcId, 0,0, kInDsvFl | kDoubleDsvFl, "Signal Attack/Decay milliseconds.",
  3548. 1, "alpha", kPhatAlphaRcId, 0,0, kInDsvFl | kDoubleDsvFl, "PHAT alpha coefficient.",
  3549. 1, "mult", kPhatMultRcId, 0,0, kInDsvFl | kUIntDsvFl, "PHAT multiplier coefficient.",
  3550. 1, "in", kInRcId, 0,1, kInDsvFl | kAudioBufDsvFl,"Audio input",
  3551. 1, "out", kOutRcId, 0,1, kOutDsvFl | kAudioBufDsvFl,"Audio output",
  3552. 0 );
  3553. p->r = cmReflectCalcAlloc(ctx->cmProcCtx, NULL, NULL, 0, 0 );
  3554. cmDspSetDefaultUInt( ctx, &p->inst, kLfsrN_RcId, 0, 8);
  3555. cmDspSetDefaultUInt( ctx, &p->inst, kMlsCoeff0RcId, 0, 0x8e);
  3556. cmDspSetDefaultUInt( ctx, &p->inst, kMlsCoeff1RcId, 0, 0x96);
  3557. cmDspSetDefaultUInt( ctx, &p->inst, kSmpPerChipRcId, 0, 64);
  3558. cmDspSetDefaultDouble( ctx, &p->inst, kRcosBetaRcId, 0, 0.5);
  3559. cmDspSetDefaultUInt( ctx, &p->inst, kRcosOS_RcId, 0, 4);
  3560. cmDspSetDefaultDouble( ctx, &p->inst, kCarrierHzRcId, 0, 2500.0);
  3561. cmDspSetDefaultDouble( ctx, &p->inst, kAtkDcyMsRcId, 0, 50.0);
  3562. cmDspSetDefaultDouble( ctx, &p->inst, kPhatAlphaRcId, 0, 0.5);
  3563. cmDspSetDefaultUInt( ctx, &p->inst, kPhatMultRcId, 0, 1);
  3564. return &p->inst;
  3565. }
  3566. cmDspRC_t _cmDspReflectCalcSetup( cmDspCtx_t* ctx, cmDspInst_t* inst )
  3567. {
  3568. cmDspRC_t rc = kOkDspRC;
  3569. cmDspReflectCalc_t* p = (cmDspReflectCalc_t*)inst;
  3570. cmGoldSigArg_t gsa;
  3571. gsa.chN = 1;
  3572. gsa.srate = cmDspSampleRate(ctx);
  3573. gsa.lfsrN = cmDspUInt(inst,kLfsrN_RcId);
  3574. gsa.mlsCoeff0 = cmDspUInt(inst,kMlsCoeff0RcId);
  3575. gsa.mlsCoeff1 = cmDspUInt(inst,kMlsCoeff1RcId);
  3576. gsa.samplesPerChip = cmDspUInt(inst,kSmpPerChipRcId);
  3577. gsa.rcosBeta = cmDspDouble(inst,kRcosBetaRcId);
  3578. gsa.rcosOSFact = cmDspUInt(inst,kRcosOS_RcId);
  3579. gsa.carrierHz = cmDspDouble(inst,kCarrierHzRcId);
  3580. gsa.envMs = cmDspDouble(inst,kAtkDcyMsRcId);
  3581. double phatAlpha = cmDspDouble(inst,kPhatAlphaRcId);
  3582. unsigned phatMult = cmDspUInt(inst,kPhatMultRcId);
  3583. if( cmReflectCalcInit(p->r,&gsa,phatAlpha,phatMult) != cmOkRC )
  3584. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to initialize the internal ReflectCalc detector.");
  3585. return rc;
  3586. }
  3587. cmDspRC_t _cmDspReflectCalcFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3588. {
  3589. cmDspRC_t rc = kOkDspRC;
  3590. cmDspReflectCalc_t* p = (cmDspReflectCalc_t*)inst;
  3591. cmReflectCalcFree(&p->r);
  3592. return rc;
  3593. }
  3594. cmDspRC_t _cmDspReflectCalcReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3595. {
  3596. //cmDspReflectCalc_t* p = (cmDspReflectCalc_t*)inst;
  3597. cmDspApplyAllDefaults(ctx,inst);
  3598. return _cmDspReflectCalcSetup(ctx, inst );
  3599. }
  3600. cmDspRC_t _cmDspReflectCalcExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3601. {
  3602. cmDspRC_t rc = kOkDspRC;
  3603. cmDspReflectCalc_t* p = (cmDspReflectCalc_t*)inst;
  3604. const cmSample_t* xV = cmDspAudioBuf(ctx,inst,kInRcId,0);
  3605. unsigned xN = cmDspAudioBufSmpCount(ctx,inst,kInRcId,0);
  3606. cmSample_t* yV = cmDspAudioBuf(ctx,inst,kOutRcId,0);
  3607. unsigned yN = cmDspAudioBufSmpCount(ctx,inst,kOutRcId,0);
  3608. if( xV != NULL && yV != NULL )
  3609. {
  3610. assert( xN == yN );
  3611. cmReflectCalcExec(p->r,xV,yV,xN);
  3612. }
  3613. return rc;
  3614. }
  3615. cmDspRC_t _cmDspReflectCalcRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3616. {
  3617. //cmDspReflectCalc_t* p = (cmDspReflectCalc_t*)inst;
  3618. cmDspSetEvent(ctx,inst,evt);
  3619. return kOkDspRC;
  3620. }
  3621. cmDspClass_t* cmReflectCalcClassCons( cmDspCtx_t* ctx )
  3622. {
  3623. cmDspClassSetup(&_cmReflectCalcDC,ctx,"ReflectCalc",
  3624. NULL,
  3625. _cmDspReflectCalcAlloc,
  3626. _cmDspReflectCalcFree,
  3627. _cmDspReflectCalcReset,
  3628. _cmDspReflectCalcExec,
  3629. _cmDspReflectCalcRecv,
  3630. NULL,
  3631. NULL,
  3632. "Reflecttion time calculator");
  3633. return &_cmReflectCalcDC;
  3634. }
  3635. //------------------------------------------------------------------------------------------------------------
  3636. //)
  3637. //( { label:cmDspEchoCancel file_desc:"Normalized least mean squares echo canceller." kw:[sunit gutim] }
  3638. enum
  3639. {
  3640. kMuEcId,
  3641. kImpRespN_EcId,
  3642. kDelayN_EcId,
  3643. kBypassEcId,
  3644. kUnfiltInEcId,
  3645. kFiltInEcId,
  3646. kOutEcId
  3647. };
  3648. cmDspClass_t _cmEchoCancelDC;
  3649. typedef struct
  3650. {
  3651. cmDspInst_t inst;
  3652. cmNlmsEc_t* r;
  3653. } cmDspEchoCancel_t;
  3654. cmDspInst_t* _cmDspEchoCancelAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  3655. {
  3656. // if( va_cnt !=3 )
  3657. // {
  3658. // cmDspClassErr(ctx,classPtr,kVarArgParseFailDspRC,"The 'EchoCancel' constructor must have two arguments: a channel count and frequency array.");
  3659. // return NULL;
  3660. // }
  3661. cmDspEchoCancel_t* p = cmDspInstAllocV(cmDspEchoCancel_t,ctx,classPtr,instSymId,id,storeSymId,va_cnt,vl,
  3662. 1, "mu", kMuEcId, 0,0, kInDsvFl | kDoubleDsvFl, "NLSM mu coefficient.",
  3663. 1, "irN", kImpRespN_EcId, 0,0, kInDsvFl | kUIntDsvFl, "Filter impulse response length in samples.",
  3664. 1, "delayN", kDelayN_EcId, 0,0, kInDsvFl | kUIntDsvFl, "Fixed feedback delay in samples.",
  3665. 1, "bypass", kBypassEcId, 0,0, kInDsvFl | kBoolDsvFl, "Bypass enable flag.",
  3666. 1, "uf_in", kUnfiltInEcId, 0,1, kInDsvFl | kAudioBufDsvFl, "Unfiltered audio input",
  3667. 1, "f_in", kFiltInEcId, 0,1, kInDsvFl | kAudioBufDsvFl, "Filtered audio input",
  3668. 1, "out", kOutEcId, 0,1, kOutDsvFl | kAudioBufDsvFl, "Audio output",
  3669. 0 );
  3670. p->r = cmNlmsEcAlloc(ctx->cmProcCtx, NULL, 0, 0,0,0 );
  3671. cmDspSetDefaultDouble( ctx, &p->inst, kMuEcId, 0, 0.1);
  3672. cmDspSetDefaultUInt( ctx, &p->inst, kImpRespN_EcId, 0, 2048);
  3673. cmDspSetDefaultUInt( ctx, &p->inst, kDelayN_EcId, 0, 1765);
  3674. cmDspSetDefaultBool( ctx, &p->inst, kBypassEcId, 0, false);
  3675. return &p->inst;
  3676. }
  3677. cmDspRC_t _cmDspEchoCancelSetup( cmDspCtx_t* ctx, cmDspInst_t* inst )
  3678. {
  3679. cmDspRC_t rc = kOkDspRC;
  3680. cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
  3681. double mu = cmDspDouble(inst,kMuEcId);
  3682. unsigned hN = cmDspUInt(inst,kImpRespN_EcId);
  3683. unsigned delayN = cmDspUInt(inst,kDelayN_EcId);
  3684. if( cmNlmsEcInit(p->r,cmDspSampleRate(ctx),mu,hN,delayN) != cmOkRC )
  3685. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to initialize the internal echo canceller.");
  3686. return rc;
  3687. }
  3688. cmDspRC_t _cmDspEchoCancelFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3689. {
  3690. cmDspRC_t rc = kOkDspRC;
  3691. cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
  3692. cmNlmsEcWrite(p->r, "/Users/kevin/temp/kc");
  3693. cmNlmsEcFree(&p->r);
  3694. return rc;
  3695. }
  3696. cmDspRC_t _cmDspEchoCancelReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3697. {
  3698. //cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
  3699. cmDspApplyAllDefaults(ctx,inst);
  3700. return _cmDspEchoCancelSetup(ctx, inst );
  3701. }
  3702. cmDspRC_t _cmDspEchoCancelExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3703. {
  3704. cmDspRC_t rc = kOkDspRC;
  3705. cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
  3706. bool bypassFl = true; //cmDspBool(inst,kBypassEcId);
  3707. const cmSample_t* fV = cmDspAudioBuf(ctx,inst,kFiltInEcId,0);
  3708. unsigned fN = cmDspAudioBufSmpCount(ctx,inst,kFiltInEcId,0);
  3709. const cmSample_t* uV = cmDspAudioBuf(ctx,inst,kUnfiltInEcId,0);
  3710. unsigned uN = cmDspAudioBufSmpCount(ctx,inst,kUnfiltInEcId,0);
  3711. cmSample_t* yV = cmDspAudioBuf(ctx,inst,kOutEcId,0);
  3712. unsigned yN = cmDspAudioBufSmpCount(ctx,inst,kOutEcId,0);
  3713. assert( fN==uN && fN==yN );
  3714. if( bypassFl )
  3715. {
  3716. cmVOS_Copy(yV,yN,uV);
  3717. }
  3718. else
  3719. {
  3720. if( fV !=NULL && uV != NULL && yV != NULL )
  3721. {
  3722. assert( uN == yN && fN == yN );
  3723. cmNlmsEcExec(p->r,uV,fV,yV,yN);
  3724. }
  3725. }
  3726. return rc;
  3727. }
  3728. cmDspRC_t _cmDspEchoCancelRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  3729. {
  3730. cmDspEchoCancel_t* p = (cmDspEchoCancel_t*)inst;
  3731. cmDspSetEvent(ctx,inst,evt);
  3732. if( p->r != NULL )
  3733. {
  3734. switch(evt->dstVarId)
  3735. {
  3736. case kMuEcId:
  3737. cmNlmsEcSetMu( p->r, cmDspReal(inst,kMuEcId));
  3738. break;
  3739. case kImpRespN_EcId:
  3740. cmNlmsEcSetIrN( p->r, cmDspUInt(inst,kImpRespN_EcId));
  3741. break;
  3742. case kDelayN_EcId:
  3743. cmNlmsEcSetDelayN( p->r, cmDspUInt(inst,kDelayN_EcId));
  3744. break;
  3745. case kBypassEcId:
  3746. printf("EC bypass:%i\n",cmDspBool(inst,kBypassEcId));
  3747. break;
  3748. }
  3749. }
  3750. printf("mu:%f dN:%i hN:%i\n",p->r->mu,p->r->delayN,p->r->hN);
  3751. return kOkDspRC;
  3752. }
  3753. cmDspClass_t* cmEchoCancelClassCons( cmDspCtx_t* ctx )
  3754. {
  3755. cmDspClassSetup(&_cmEchoCancelDC,ctx,"EchoCancel",
  3756. NULL,
  3757. _cmDspEchoCancelAlloc,
  3758. _cmDspEchoCancelFree,
  3759. _cmDspEchoCancelReset,
  3760. _cmDspEchoCancelExec,
  3761. _cmDspEchoCancelRecv,
  3762. NULL,
  3763. NULL,
  3764. "Echo canceller");
  3765. return &_cmEchoCancelDC;
  3766. }
  3767. //)