libcm is a C development framework with an emphasis on audio signal processing applications.
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

cmDspKr.c 67KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244
  1. #include "cmPrefix.h"
  2. #include "cmGlobal.h"
  3. #include "cmFloatTypes.h"
  4. #include "cmComplexTypes.h"
  5. #include "cmRpt.h"
  6. #include "cmErr.h"
  7. #include "cmCtx.h"
  8. #include "cmMem.h"
  9. #include "cmMallocDebug.h"
  10. #include "cmLinkedHeap.h"
  11. #include "cmFile.h"
  12. #include "cmSymTbl.h"
  13. #include "cmJson.h"
  14. #include "cmText.h"
  15. #include "cmPrefs.h"
  16. #include "cmDspValue.h"
  17. #include "cmMsgProtocol.h"
  18. #include "cmThread.h"
  19. #include "cmUdpPort.h"
  20. #include "cmUdpNet.h"
  21. #include "cmAudioSys.h"
  22. #include "cmDspCtx.h"
  23. #include "cmDspClass.h"
  24. #include "cmDspStore.h"
  25. #include "cmDspUi.h"
  26. #include "cmDspSys.h"
  27. #include "cmMath.h"
  28. #include "cmAudioFile.h"
  29. #include "cmFileSys.h"
  30. #include "cmProcObj.h"
  31. #include "cmProcTemplateMain.h"
  32. #include "cmProc.h"
  33. #include "cmMidi.h"
  34. #include "cmProc2.h"
  35. #include "cmVectOpsTemplateMain.h"
  36. #include "cmAudioFile.h"
  37. #include "cmMidiFile.h"
  38. #include "cmTimeLine.h"
  39. #include "cmScore.h"
  40. #include "cmProc4.h"
  41. enum
  42. {
  43. kWndSmpCntKrId,
  44. kHopFactKrId,
  45. kModeKrId,
  46. kThreshKrId,
  47. kLwrSlopeKrId,
  48. kUprSlopeKrId,
  49. kOffsetKrId,
  50. kInvertKrId,
  51. kBypassKrId,
  52. kWetKrId,
  53. kAudioInKrId,
  54. kAudioOutKrId
  55. };
  56. typedef struct
  57. {
  58. cmDspInst_t inst;
  59. cmCtx* ctx;
  60. cmSpecDist_t* sdp;
  61. } cmDspKr_t;
  62. cmDspClass_t _cmKrDC;
  63. //==========================================================================================================================================
  64. cmDspInst_t* _cmDspKrAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  65. {
  66. cmDspVarArg_t args[] =
  67. {
  68. { "wndn", kWndSmpCntKrId, 0, 0, kInDsvFl | kUIntDsvFl | kReqArgDsvFl, "Window sample count" },
  69. { "hopf", kHopFactKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Hop factor" },
  70. { "mode", kModeKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Mode 0=bypass 1=basic 2=spec cnt 3=amp env" },
  71. { "thrh", kThreshKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Threshold" },
  72. { "lwrs", kLwrSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Lower Slope"},
  73. { "uprs", kUprSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"},
  74. { "offs", kOffsetKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Offset"},
  75. { "invt", kInvertKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Invert"},
  76. { "bypass", kBypassKrId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Bypass enable flag." },
  77. { "wet", kWetKrId, 0, 0, kInDsvFl | kSampleDsvFl, "Wet mix level."},
  78. { "in", kAudioInKrId, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" },
  79. { "out", kAudioOutKrId, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" },
  80. { NULL, 0, 0, 0, 0 }
  81. };
  82. cmDspKr_t* p = cmDspInstAlloc(cmDspKr_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  83. unsigned defWndSmpCnt = cmDspDefaultUInt(&p->inst,kWndSmpCntKrId);
  84. unsigned wndSmpCnt = cmNextPowerOfTwo( defWndSmpCnt );
  85. cmDspSetDefaultUInt( ctx,&p->inst, kWndSmpCntKrId, defWndSmpCnt, wndSmpCnt );
  86. cmDspSetDefaultUInt( ctx,&p->inst, kHopFactKrId, 0, 4 );
  87. cmDspSetDefaultUInt( ctx,&p->inst, kModeKrId, 0, kBasicModeSdId );
  88. cmDspSetDefaultDouble( ctx,&p->inst, kThreshKrId, 0, 60.0 );
  89. cmDspSetDefaultDouble( ctx,&p->inst, kLwrSlopeKrId, 0, 2.0 );
  90. cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKrId, 0, 0.0 );
  91. cmDspSetDefaultDouble( ctx,&p->inst, kOffsetKrId, 0, 30.0);
  92. cmDspSetDefaultUInt( ctx,&p->inst, kInvertKrId, 0, 0 );
  93. cmDspSetDefaultUInt( ctx,&p->inst, kBypassKrId, 0, 0 );
  94. cmDspSetDefaultSample( ctx,&p->inst, kWetKrId, 0, 1.0);
  95. //_cmDspKrCmInit(ctx,p); // initialize the cm library
  96. p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH);
  97. return &p->inst;
  98. }
  99. cmDspRC_t _cmDspKrFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  100. {
  101. cmDspRC_t rc = kOkDspRC;
  102. cmDspKr_t* p = (cmDspKr_t*)inst;
  103. cmSpecDistFree(&p->sdp);
  104. cmCtxFree(&p->ctx);
  105. //_cmDspKrCmFinal(ctx,p); // finalize the cm library
  106. return rc;
  107. }
  108. cmDspRC_t _cmDspKrSetup(cmDspCtx_t* ctx, cmDspKr_t* p )
  109. {
  110. cmDspRC_t rc = kOkDspRC;
  111. unsigned wndSmpCnt = cmDspUInt(&p->inst,kWndSmpCntKrId);
  112. unsigned hopFact = cmDspUInt(&p->inst,kHopFactKrId);
  113. unsigned olaWndTypeId =kHannWndId;
  114. cmSpecDistFree(&p->sdp);
  115. p->sdp = cmSpecDistAlloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId);
  116. assert(p->sdp != NULL );
  117. if((rc = cmDspZeroAudioBuf(ctx,&p->inst,kAudioOutKrId)) != kOkDspRC )
  118. return rc;
  119. return rc;
  120. }
  121. cmDspRC_t _cmDspKrReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  122. {
  123. cmDspKr_t* p = (cmDspKr_t*)inst;
  124. cmDspRC_t rc;
  125. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  126. return rc;
  127. return _cmDspKrSetup(ctx,p);
  128. }
  129. cmDspRC_t _cmDspKrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  130. {
  131. cmDspKr_t* p = (cmDspKr_t*)inst;
  132. cmDspRC_t rc = kOkDspRC;
  133. unsigned iChIdx = 0;
  134. const cmSample_t* ip = cmDspAudioBuf(ctx,inst,kAudioInKrId,iChIdx);
  135. unsigned iSmpCnt = cmDspVarRows(inst,kAudioInKrId);
  136. // if no connected
  137. if( iSmpCnt == 0 )
  138. return rc;
  139. unsigned oChIdx = 0;
  140. cmSample_t* op = cmDspAudioBuf(ctx,inst,kAudioOutKrId,oChIdx);
  141. unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId);
  142. const cmSample_t* sp;
  143. cmSample_t wet = cmDspSample(inst,kWetKrId);
  144. cmSpecDistExec(p->sdp,ip,iSmpCnt);
  145. if((sp = cmSpecDistOut(p->sdp)) != NULL )
  146. {
  147. cmVOS_MultVVS(op,oSmpCnt,sp,wet);
  148. }
  149. if( wet<1.0 )
  150. cmVOS_MultSumVVS(op,oSmpCnt,ip,1.0-wet);
  151. return rc;
  152. }
  153. cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  154. {
  155. cmDspKr_t* p = (cmDspKr_t*)inst;
  156. cmDspRC_t rc = kOkDspRC;
  157. cmDspSetEvent(ctx,inst,evt);
  158. switch( evt->dstVarId )
  159. {
  160. case kWndSmpCntKrId:
  161. case kHopFactKrId:
  162. _cmDspKrSetup(ctx,p);
  163. // THIS IS A HACK
  164. // WHEN WND OR HOP CHANGE THE RESULTING CHANGES
  165. // SHOULD BE ISOLATED IN cmSpecDist() AND THE
  166. // CURRENT STATE OF THE PARAMETERS SHOULD NOT BE
  167. // LOST - IF THE CHANGES WERE ISOLATED WITHIN PVANL
  168. // AND PVSYN IT MIGHT BE POSSIBLE TO DO WITH
  169. // MINIMAL AUDIO INTERUPTION.
  170. p->sdp->mode = cmDspUInt(inst,kModeKrId);
  171. p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
  172. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
  173. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
  174. p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
  175. p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
  176. printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt);
  177. break;
  178. case kModeKrId:
  179. p->sdp->mode = cmDspUInt(inst,kModeKrId);
  180. printf("mode:%i\n",p->sdp->mode);
  181. break;
  182. case kThreshKrId:
  183. p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
  184. //printf("thr:p:%p sdp:%p %f\n",p,p->sdp,p->sdp->thresh);
  185. break;
  186. case kUprSlopeKrId:
  187. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
  188. //printf("upr slope:%f\n",p->sdp->uprSlope);
  189. break;
  190. case kLwrSlopeKrId:
  191. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
  192. //printf("upr slope:%f\n",p->sdp->lwrSlope);
  193. break;
  194. case kOffsetKrId:
  195. p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
  196. break;
  197. case kInvertKrId:
  198. p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
  199. break;
  200. case kWetKrId:
  201. break;
  202. default:
  203. { assert(0); }
  204. }
  205. return rc;
  206. }
  207. struct cmDspClass_str* cmKrClassCons( cmDspCtx_t* ctx )
  208. {
  209. cmDspClassSetup(&_cmKrDC,ctx,"Kr",
  210. NULL,
  211. _cmDspKrAlloc,
  212. _cmDspKrFree,
  213. _cmDspKrReset,
  214. _cmDspKrExec,
  215. _cmDspKrRecv,
  216. NULL,NULL,
  217. "Fourier based non-linear transformer.");
  218. return &_cmKrDC;
  219. }
  220. //==========================================================================================================================================
  221. // Time Line UI Object
  222. enum
  223. {
  224. kTlFileTlId,
  225. kPrefixPathTlId,
  226. kSelTlId,
  227. kCursTlId,
  228. kResetTlId,
  229. kAudFnTlId,
  230. kAudLblTlId,
  231. kMidiFnTlId,
  232. kMidiLblTlId,
  233. kBegAudSmpIdxTlId,
  234. kEndAudSmpIdxTlId,
  235. kBegMidiSmpIdxTlId,
  236. kEndMidiSmpIdxTlId
  237. };
  238. cmDspClass_t _cmTimeLineDC;
  239. typedef struct
  240. {
  241. cmDspInst_t inst;
  242. cmTlH_t tlH;
  243. unsigned afIdx;
  244. } cmDspTimeLine_t;
  245. cmDspInst_t* _cmDspTimeLineAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  246. {
  247. cmDspVarArg_t args[] =
  248. {
  249. { "tlfile", kTlFileTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Time line file." },
  250. { "path", kPrefixPathTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Time line data file prefix path" },
  251. { "sel", kSelTlId, 0, 0, kInDsvFl | kOutDsvFl | kUIntDsvFl, "Selected marker id."},
  252. { "curs", kCursTlId, 0, 0, kInDsvFl | kUIntDsvFl, "Current audio file index."},
  253. { "reset", kResetTlId, 0, 0, kInDsvFl | kSymDsvFl, "Resend all outputs." },
  254. { "afn", kAudFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected Audio file." },
  255. { "albl", kAudLblTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Select Audio file time line label."},
  256. { "mfn", kMidiFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected MIDI file." },
  257. { "mlbl", kMidiLblTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Select MIDI file time line label."},
  258. { "absi", kBegAudSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "Begin audio sample index."},
  259. { "aesi", kEndAudSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "End audio sample index."},
  260. { "mbsi", kBegMidiSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "Begin MIDI sample index."},
  261. { "mesi", kEndMidiSmpIdxTlId, 0, 0, kOutDsvFl | kIntDsvFl, "End MIDI sample index."},
  262. { NULL, 0, 0, 0, 0 }
  263. };
  264. cmDspTimeLine_t* p = cmDspInstAlloc(cmDspTimeLine_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  265. cmDspSetDefaultUInt( ctx, &p->inst, kSelTlId, 0, cmInvalidId);
  266. cmDspSetDefaultUInt( ctx, &p->inst, kCursTlId, 0, 0);
  267. cmDspSetDefaultStrcz(ctx, &p->inst, kAudFnTlId, NULL, "");
  268. cmDspSetDefaultStrcz(ctx, &p->inst, kAudLblTlId, NULL, "");
  269. cmDspSetDefaultStrcz(ctx, &p->inst, kMidiFnTlId, NULL, "");
  270. cmDspSetDefaultStrcz(ctx, &p->inst, kMidiLblTlId, NULL, "");
  271. cmDspSetDefaultInt( ctx, &p->inst, kBegAudSmpIdxTlId, 0, cmInvalidIdx);
  272. cmDspSetDefaultInt( ctx, &p->inst, kEndAudSmpIdxTlId, 0, cmInvalidIdx);
  273. cmDspSetDefaultInt( ctx, &p->inst, kBegMidiSmpIdxTlId, 0, cmInvalidIdx);
  274. cmDspSetDefaultInt( ctx, &p->inst, kEndMidiSmpIdxTlId, 0, cmInvalidIdx);
  275. // create the UI control
  276. cmDspUiTimeLineCreate(ctx,&p->inst,kTlFileTlId,kPrefixPathTlId,kSelTlId,kCursTlId);
  277. p->tlH = cmTimeLineNullHandle;
  278. return &p->inst;
  279. }
  280. cmDspRC_t _cmDspTimeLineFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  281. {
  282. cmDspRC_t rc = kOkDspRC;
  283. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  284. if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
  285. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Time-line finalize failed.");
  286. return rc;
  287. }
  288. cmDspRC_t _cmDspTimeLineReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  289. {
  290. cmDspRC_t rc = kOkDspRC;
  291. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  292. cmDspApplyAllDefaults(ctx,inst);
  293. const cmChar_t* tlFn;
  294. const cmChar_t* tlPrePath = cmDspStrcz(inst,kPrefixPathTlId);
  295. if((tlFn = cmDspStrcz(inst, kTlFileTlId )) != NULL )
  296. if( cmTimeLineInitializeFromFile(ctx->cmCtx, &p->tlH, NULL, NULL, tlFn, tlPrePath ) != kOkTlRC )
  297. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Time-line file open failed.");
  298. return rc;
  299. }
  300. cmDspRC_t _cmDspTimeLineRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  301. {
  302. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  303. switch( evt->dstVarId )
  304. {
  305. case kPrefixPathTlId:
  306. cmDspSetEvent(ctx,inst,evt);
  307. break;
  308. case kCursTlId:
  309. cmDspSetEvent(ctx,inst,evt);
  310. break;
  311. case kResetTlId:
  312. case kSelTlId:
  313. {
  314. unsigned markerId;
  315. cmDspSetEvent(ctx,inst,evt);
  316. // get the id of the selected marker
  317. if((markerId = cmDspUInt(inst,kSelTlId)) != cmInvalidId )
  318. {
  319. // get the marker object
  320. cmTlObj_t* op;
  321. if((op = cmTimeLineIdToObj(p->tlH, cmInvalidId, markerId )) != NULL )
  322. {
  323. assert(op->typeId == kMarkerTlId);
  324. p->afIdx = op->begSmpIdx;
  325. cmDspSetInt(ctx, inst, kBegAudSmpIdxTlId, op->begSmpIdx );
  326. cmDspSetInt(ctx, inst, kEndAudSmpIdxTlId, op->begSmpIdx + op->durSmpCnt );
  327. // locate the audio file assoc'd with the marker
  328. cmTlAudioFile_t* afp;
  329. if((afp = cmTimeLineAudioFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL)
  330. {
  331. cmDspSetStrcz(ctx, inst, kAudFnTlId, afp->fn );
  332. cmDspSetStrcz(ctx, inst, kAudLblTlId, afp->obj.name );
  333. }
  334. // locate the midi file assoc'd with the marker
  335. cmTlMidiFile_t* mfp;
  336. if((mfp = cmTimeLineMidiFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL )
  337. {
  338. cmDspSetInt(ctx, inst, kBegMidiSmpIdxTlId, op->seqSmpIdx - mfp->obj.seqSmpIdx );
  339. cmDspSetInt(ctx, inst, kEndMidiSmpIdxTlId, op->seqSmpIdx + op->durSmpCnt - mfp->obj.seqSmpIdx );
  340. cmDspSetStrcz(ctx, inst, kMidiFnTlId, mfp->fn );
  341. cmDspSetStrcz(ctx, inst, kMidiLblTlId,mfp->obj.name );
  342. }
  343. }
  344. }
  345. }
  346. break;
  347. default:
  348. {assert(0);}
  349. }
  350. return kOkDspRC;
  351. }
  352. struct cmDspClass_str* cmTimeLineClassCons( cmDspCtx_t* ctx )
  353. {
  354. cmDspClassSetup(&_cmTimeLineDC,ctx,"TimeLine",
  355. NULL,
  356. _cmDspTimeLineAlloc,
  357. _cmDspTimeLineFree,
  358. _cmDspTimeLineReset,
  359. NULL,
  360. _cmDspTimeLineRecv,
  361. NULL,NULL,
  362. "Time Line control.");
  363. return &_cmTimeLineDC;
  364. }
  365. //==========================================================================================================================================
  366. // Score UI Object
  367. enum
  368. {
  369. kFnScId,
  370. kSelScId,
  371. kSendScId,
  372. kStatusScId,
  373. kD0ScId,
  374. kD1ScId,
  375. kSmpIdxScId,
  376. kLocIdxScId,
  377. kEvtIdxScId,
  378. kDynScId,
  379. kValTypeScId,
  380. kValueScId
  381. };
  382. cmDspClass_t _cmScoreDC;
  383. typedef struct
  384. {
  385. cmDspInst_t inst;
  386. cmScH_t scH;
  387. cmDspCtx_t* ctx; // temporary ctx ptr used during cmScore callback in _cmDspScoreRecv()
  388. } cmDspScore_t;
  389. cmDspInst_t* _cmDspScoreAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  390. {
  391. cmDspVarArg_t args[] =
  392. {
  393. { "fn", kFnScId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." },
  394. { "sel", kSelScId, 0, 0, kInDsvFl | kOutDsvFl | kUIntDsvFl, "Selected score element index input."},
  395. { "send", kSendScId, 0, 0, kInDsvFl | kTypeDsvMask, "Resend last selected score element."},
  396. { "status", kStatusScId, 0, 0, kInDsvFl | kIntDsvFl, "Performed MIDI status value output" },
  397. { "d0", kD0ScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performed MIDI msg data byte 0" },
  398. { "d1", kD1ScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performed MIDI msg data byte 1" },
  399. { "smpidx", kSmpIdxScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performed MIDi msg time tag as a sample index." },
  400. { "loc", kLocIdxScId, 0, 0, kInDsvFl | kUIntDsvFl, "Performance score location."},
  401. { "evtidx", kEvtIdxScId, 0, 0, kOutDsvFl | kUIntDsvFl, "Performed event index of following dynamcis level."},
  402. { "dyn", kDynScId, 0, 0, kOutDsvFl | kUIntDsvFl, "Dynamic level of previous event index."},
  403. { "type", kValTypeScId,0, 0, kOutDsvFl | kUIntDsvFl, "Output variable type."},
  404. { "value", kValueScId, 0, 0, kOutDsvFl | kDoubleDsvFl, "Output variable value."},
  405. { NULL, 0, 0, 0, 0 }
  406. };
  407. cmDspScore_t* p = cmDspInstAlloc(cmDspScore_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  408. cmDspSetDefaultUInt( ctx, &p->inst, kSelScId, 0, cmInvalidId);
  409. // create the UI control
  410. cmDspUiScoreCreate(ctx,&p->inst,kFnScId,kSelScId,kSmpIdxScId,kD0ScId,kD1ScId,kLocIdxScId,kEvtIdxScId,kDynScId,kValTypeScId,kValueScId);
  411. p->scH = cmScNullHandle;
  412. return &p->inst;
  413. }
  414. cmDspRC_t _cmDspScoreFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  415. {
  416. cmDspRC_t rc = kOkDspRC;
  417. cmDspScore_t* p = (cmDspScore_t*)inst;
  418. if( cmScoreFinalize(&p->scH) != kOkTlRC )
  419. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Score finalize failed.");
  420. return rc;
  421. }
  422. // Callback from cmScore triggered from _cmDspScoreRecv() during call to cmScoreSetPerfEvent().
  423. void _cmDspScoreCb( void* arg, const void* data, unsigned byteCnt )
  424. {
  425. cmDspInst_t* inst = (cmDspInst_t*)arg;
  426. cmDspScore_t* p = (cmDspScore_t*)inst;
  427. cmScMsg_t m;
  428. if( cmScoreDecode(data,byteCnt,&m) == kOkScRC )
  429. {
  430. switch( m.typeId )
  431. {
  432. case kDynMsgScId:
  433. cmDspSetUInt( p->ctx,inst, kEvtIdxScId, m.u.dyn.evtIdx );
  434. cmDspSetUInt( p->ctx,inst, kDynScId, m.u.dyn.dynLvl );
  435. break;
  436. case kVarMsgScId:
  437. cmDspSetUInt( p->ctx,inst, kValTypeScId, m.u.meas.varId);
  438. cmDspSetDouble(p->ctx,inst, kValueScId, m.u.meas.value);
  439. break;
  440. default:
  441. { assert(0); }
  442. }
  443. }
  444. }
  445. cmDspRC_t _cmDspScoreReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  446. {
  447. cmDspRC_t rc = kOkDspRC;
  448. cmDspScore_t* p = (cmDspScore_t*)inst;
  449. const cmChar_t* tlFn = NULL;
  450. unsigned* dynRefArray = NULL;
  451. unsigned dynRefCnt = 0;
  452. cmDspApplyAllDefaults(ctx,inst);
  453. if( cmDspRsrcUIntArray(ctx->dspH, &dynRefCnt, &dynRefArray, "dynRef", NULL ) != kOkDspRC )
  454. {
  455. rc = cmErrMsg(&inst->classPtr->err, kRsrcNotFoundDspRC, "The dynamics reference array resource was not found.");
  456. goto errLabel;
  457. }
  458. if((tlFn = cmDspStrcz(inst, kFnScId )) != NULL )
  459. if( cmScoreInitialize(ctx->cmCtx, &p->scH, tlFn, cmDspSampleRate(ctx), dynRefArray, dynRefCnt, _cmDspScoreCb, p, cmSymTblNullHandle ) != kOkTlRC )
  460. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Score file open failed.");
  461. errLabel:
  462. return rc;
  463. }
  464. cmDspRC_t _cmDspScoreRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  465. {
  466. cmDspScore_t* p = (cmDspScore_t*)inst;
  467. if( evt->dstVarId == kSendScId )
  468. {
  469. unsigned selIdx;
  470. if((selIdx = cmDspUInt(inst,kSelScId)) != cmInvalidIdx )
  471. {
  472. cmDspSetUInt(ctx,inst,kSelScId, selIdx );
  473. cmScoreClearPerfInfo(p->scH);
  474. }
  475. return kOkDspRC;
  476. }
  477. cmDspSetEvent(ctx,inst,evt);
  478. switch( evt->dstVarId )
  479. {
  480. case kSelScId:
  481. cmScoreClearPerfInfo(p->scH);
  482. break;
  483. case kStatusScId:
  484. //printf("st:%x\n",cmDspUInt(inst,kStatusScId));
  485. break;
  486. case kLocIdxScId:
  487. {
  488. assert( cmDspUInt(inst,kStatusScId ) == kNoteOnMdId );
  489. p->ctx = ctx; // setup p->ctx for use in _cmDspScoreCb()
  490. // this call may result in callbacks to _cmDspScoreCb()
  491. cmScoreExecPerfEvent(p->scH, cmDspUInt(inst,kLocIdxScId), cmDspUInt(inst,kSmpIdxScId), cmDspUInt(inst,kD0ScId), cmDspUInt(inst,kD1ScId) );
  492. }
  493. break;
  494. }
  495. return kOkDspRC;
  496. }
  497. struct cmDspClass_str* cmScoreClassCons( cmDspCtx_t* ctx )
  498. {
  499. cmDspClassSetup(&_cmScoreDC,ctx,"Score",
  500. NULL,
  501. _cmDspScoreAlloc,
  502. _cmDspScoreFree,
  503. _cmDspScoreReset,
  504. NULL,
  505. _cmDspScoreRecv,
  506. NULL,NULL,
  507. "Score control.");
  508. return &_cmScoreDC;
  509. }
  510. //==========================================================================================================================================
  511. // MIDI File Player
  512. enum
  513. {
  514. kFnMfId,
  515. kSelMfId,
  516. kBsiMfId,
  517. kEsiMfId,
  518. kStatusMfId,
  519. kD0MfId,
  520. kD1MfId,
  521. kSmpIdxMfId,
  522. kIdMfId
  523. };
  524. cmDspClass_t _cmMidiFilePlayDC;
  525. typedef struct
  526. {
  527. cmDspInst_t inst;
  528. cmMidiFileH_t mfH;
  529. unsigned curMsgIdx; // current midi file msg index
  530. int csi; // current sample index
  531. int bsi; // starting sample index
  532. int esi; // ending sample index
  533. unsigned startSymId;
  534. unsigned stopSymId;
  535. unsigned contSymId;
  536. bool errFl;
  537. } cmDspMidiFilePlay_t;
  538. /*
  539. 'bsi' and 'esi' give the starting and ending sample for MIDI file playback.
  540. These indexes are relative to the start of the file.
  541. When the player recieves a 'start' msg it sets the current sample index
  542. 'si' to 'bsi' and begins scanning for the next note to play.
  543. On each call to the _cmDspMidiFilePlayExec() msgs that fall in the interval
  544. si:si+sPc-1 will be transmitted. (where sPc are the number of samples per DSP cycle).
  545. */
  546. cmDspInst_t* _cmDspMidiFilePlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  547. {
  548. cmDspVarArg_t args[] =
  549. {
  550. { "fn", kFnMfId, 0, 0, kInDsvFl | kStrzDsvFl, "File name"},
  551. { "sel", kSelMfId, 0, 0, kInDsvFl | kSymDsvFl, "start | stop | continue" },
  552. { "bsi", kBsiMfId, 0, 0, kInDsvFl | kIntDsvFl, "Starting sample." },
  553. { "esi", kEsiMfId, 0, 0, kInDsvFl | kIntDsvFl, "Ending sample."},
  554. { "status", kStatusMfId, 0, 0, kOutDsvFl | kIntDsvFl, "Status value output" },
  555. { "d0", kD0MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 0" },
  556. { "d1", kD1MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 1" },
  557. { "smpidx", kSmpIdxMfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Msg time tag as a sample index." },
  558. { "id", kIdMfId, 0, 0, kOutDsvFl | kUIntDsvFl, "MIDI file msg unique id."},
  559. { NULL, 0, 0, 0, 0 }
  560. };
  561. cmDspMidiFilePlay_t* p = cmDspInstAlloc(cmDspMidiFilePlay_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  562. p->startSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"start");
  563. p->stopSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"stop");
  564. p->contSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"continue");
  565. p->mfH = cmMidiFileNullHandle;
  566. cmDspSetDefaultStrcz( ctx, &p->inst, kFnMfId, NULL, "");
  567. cmDspSetDefaultSymbol(ctx, &p->inst, kSelMfId, p->stopSymId);
  568. cmDspSetDefaultInt( ctx, &p->inst, kBsiMfId, 0, 0);
  569. cmDspSetDefaultInt( ctx, &p->inst, kEsiMfId, 0, 0);
  570. cmDspSetDefaultUInt( ctx, &p->inst, kStatusMfId, 0, 0);
  571. cmDspSetDefaultUInt( ctx, &p->inst, kD0MfId, 0, 0);
  572. cmDspSetDefaultUInt( ctx, &p->inst, kD1MfId, 0, 0);
  573. return &p->inst;
  574. }
  575. cmDspRC_t _cmDspMidiFilePlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  576. {
  577. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  578. if( cmMidiFileClose(&p->mfH) )
  579. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "MIDI file close failed.");
  580. return kOkDspRC;
  581. }
  582. // return the index of the msg following smpIdx
  583. unsigned _cmDspMidiFilePlaySeekMsgIdx( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned smpIdx )
  584. {
  585. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  586. if( cmMidiFileIsValid(p->mfH) == false )
  587. {
  588. cmErrMsg(&inst->classPtr->err, kInvalidStateDspRC,"The MIDI file player has not been given a valid MIDI file.");
  589. return cmInvalidIdx;
  590. }
  591. unsigned i;
  592. unsigned n = cmMidiFileMsgCount(p->mfH);
  593. const cmMidiTrackMsg_t** a = cmMidiFileMsgArray(p->mfH);
  594. for(i=0; i<n; ++i)
  595. if( a[i]->dtick > smpIdx )
  596. break;
  597. return i==n ? cmInvalidIdx : i;
  598. }
  599. cmDspRC_t _cmDspMidiFilePlayOpen(cmDspCtx_t* ctx, cmDspInst_t* inst )
  600. {
  601. cmDspRC_t rc = kOkDspRC;
  602. const cmChar_t* fn = cmDspStrcz(inst,kFnMfId);
  603. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  604. p->errFl = false;
  605. if( fn==NULL || strlen(fn)==0 )
  606. return rc;
  607. if( cmMidiFileOpen( fn, &p->mfH, ctx->cmCtx ) != kOkFileRC )
  608. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "MIDI file open failed.");
  609. else
  610. {
  611. p->curMsgIdx = 0;
  612. p->bsi = cmDspInt(inst,kBsiMfId);
  613. p->esi = cmDspInt(inst,kEsiMfId);
  614. p->csi = 0;
  615. // force the first msg to occurr one quarter note into the file
  616. cmMidiFileSetDelay(p->mfH, cmMidiFileTicksPerQN(p->mfH) );
  617. // convert midi msg times to absolute time in samples
  618. cmMidiFileTickToSamples(p->mfH,cmDspSampleRate(ctx),true);
  619. }
  620. return rc;
  621. }
  622. cmDspRC_t _cmDspMidiFilePlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  623. {
  624. cmDspApplyAllDefaults(ctx,inst);
  625. return _cmDspMidiFilePlayOpen(ctx,inst);
  626. }
  627. cmDspRC_t _cmDspMidiFilePlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  628. {
  629. cmDspRC_t rc = kOkDspRC;
  630. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  631. unsigned sPc = cmDspSamplesPerCycle(ctx);
  632. if( cmDspSymbol(inst,kSelMfId) != p->stopSymId )
  633. {
  634. if( cmMidiFileIsValid(p->mfH) == false )
  635. {
  636. if( p->errFl==false )
  637. {
  638. rc = cmErrMsg(&inst->classPtr->err, kInvalidStateDspRC,"The MIDI file player has not been given a valid MIDI file.");
  639. p->errFl = true;
  640. }
  641. return rc;
  642. }
  643. const cmMidiTrackMsg_t** mpp = cmMidiFileMsgArray(p->mfH);
  644. unsigned msgN = cmMidiFileMsgCount(p->mfH);
  645. for(; p->curMsgIdx < msgN && p->csi <= mpp[p->curMsgIdx]->dtick && mpp[p->curMsgIdx]->dtick < (p->csi + sPc); ++p->curMsgIdx )
  646. {
  647. const cmMidiTrackMsg_t* mp = mpp[p->curMsgIdx];
  648. switch( mp->status )
  649. {
  650. case kNoteOffMdId:
  651. case kNoteOnMdId:
  652. case kCtlMdId:
  653. cmDspSetUInt(ctx,inst, kSmpIdxMfId, mp->dtick);
  654. cmDspSetUInt(ctx,inst, kD1MfId, mp->u.chMsgPtr->d1);
  655. cmDspSetUInt(ctx,inst, kD0MfId, mp->u.chMsgPtr->d0);
  656. cmDspSetUInt(ctx,inst, kStatusMfId, mp->status);
  657. cmDspSetUInt(ctx,inst, kIdMfId, mp->uid);
  658. break;
  659. }
  660. }
  661. }
  662. p->csi += sPc;
  663. return rc;
  664. }
  665. cmDspRC_t _cmDspMidiFilePlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  666. {
  667. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  668. cmDspSetEvent(ctx,inst,evt);
  669. switch(evt->dstVarId)
  670. {
  671. case kFnMfId:
  672. _cmDspMidiFilePlayOpen(ctx, inst );
  673. break;
  674. case kSelMfId:
  675. {
  676. if( cmDspSymbol(inst,kSelMfId)==p->startSymId )
  677. {
  678. p->csi = cmDspInt(inst,kBsiMfId);
  679. p->curMsgIdx = _cmDspMidiFilePlaySeekMsgIdx(ctx, inst, p->csi );
  680. }
  681. break;
  682. }
  683. }
  684. return kOkDspRC;
  685. }
  686. struct cmDspClass_str* cmMidiFilePlayClassCons( cmDspCtx_t* ctx )
  687. {
  688. cmDspClassSetup(&_cmMidiFilePlayDC,ctx,"MidiFilePlay",
  689. NULL,
  690. _cmDspMidiFilePlayAlloc,
  691. _cmDspMidiFilePlayFree,
  692. _cmDspMidiFilePlayReset,
  693. _cmDspMidiFilePlayExec,
  694. _cmDspMidiFilePlayRecv,
  695. NULL,NULL,
  696. "MIDI file player.");
  697. return &_cmMidiFilePlayDC;
  698. }
  699. //==========================================================================================================================================
  700. enum
  701. {
  702. kFnSfId,
  703. kBufCntSfId,
  704. kMinLkAhdSfId,
  705. kMaxWndCntSfId,
  706. kMinVelSfId,
  707. kIndexSfId,
  708. kStatusSfId,
  709. kD0SfId,
  710. kD1SfId,
  711. kSmpIdxSfId,
  712. kCmdSfId,
  713. kOutSfId,
  714. kDynSfId,
  715. kEvenSfId,
  716. kTempoSfId,
  717. kCostSfId,
  718. kSymSfId
  719. };
  720. cmDspClass_t _cmScFolDC;
  721. struct cmDspScFol_str;
  722. typedef struct
  723. {
  724. cmDspCtx_t* ctx;
  725. struct cmDspScFol_str* sfp;
  726. } cmDspScFolCbArg_t;
  727. typedef struct cmDspScFol_str
  728. {
  729. cmDspInst_t inst;
  730. cmScMatcher* sfp;
  731. cmScMeas* smp;
  732. cmScH_t scH;
  733. cmDspScFolCbArg_t arg;
  734. unsigned printSymId;
  735. unsigned quietSymId;
  736. } cmDspScFol_t;
  737. cmDspInst_t* _cmDspScFolAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  738. {
  739. cmDspVarArg_t args[] =
  740. {
  741. { "fn", kFnSfId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Score file." },
  742. { "bufcnt",kBufCntSfId, 0, 0, kInDsvFl | kUIntDsvFl, "Event buffer element count." },
  743. { "lkahd", kMinLkAhdSfId, 0, 0, kInDsvFl | kUIntDsvFl, "Minimum window look-ahead."},
  744. { "wndcnt",kMaxWndCntSfId,0, 0, kInDsvFl | kUIntDsvFl, "Maximum window length."},
  745. { "minvel",kMinVelSfId, 0, 0, kInDsvFl | kUIntDsvFl, "Minimum velocity."},
  746. { "index", kIndexSfId, 0, 0, kInDsvFl | kUIntDsvFl, "Tracking start location."},
  747. { "status",kStatusSfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI status byte"},
  748. { "d0", kD0SfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI data byte 0"},
  749. { "d1", kD1SfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI data byte 1"},
  750. { "smpidx",kSmpIdxSfId, 0, 0, kInDsvFl | kUIntDsvFl, "MIDI time tag as a sample index"},
  751. { "cmd", kCmdSfId, 0, 0, kInDsvFl | kSymDsvFl, "Command input: print | quiet"},
  752. { "out", kOutSfId, 0, 0, kOutDsvFl| kUIntDsvFl, "Current score location index."},
  753. { "dyn", kDynSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Dynamic value."},
  754. { "even", kEvenSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Evenness value."},
  755. { "tempo", kTempoSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Tempo value."},
  756. { "cost", kCostSfId, 0, 0, kOutDsvFl| kDoubleDsvFl, "Match cost value."},
  757. { "sym", kSymSfId, 0, 0, kOutDsvFl| kSymDsvFl, "Symbol associated with a global variable which has changed value."},
  758. { NULL, 0, 0, 0, 0, NULL }
  759. };
  760. cmDspScFol_t* p;
  761. if((p = cmDspInstAlloc(cmDspScFol_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl)) == NULL )
  762. return NULL;
  763. p->sfp = cmScMatcherAlloc(ctx->cmProcCtx, NULL, 0, cmScNullHandle, 0, 0, NULL, NULL );
  764. p->smp = cmScMeasAlloc( ctx->cmProcCtx, NULL, cmScNullHandle, 0, NULL, 0 );
  765. p->printSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"print");
  766. p->quietSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"quiet");
  767. cmDspSetDefaultUInt( ctx, &p->inst, kBufCntSfId, 0, 7);
  768. cmDspSetDefaultUInt( ctx, &p->inst, kMaxWndCntSfId, 0, 10);
  769. cmDspSetDefaultUInt( ctx, &p->inst, kMinLkAhdSfId, 0, 3);
  770. cmDspSetDefaultUInt( ctx, &p->inst, kMinVelSfId, 0, 5);
  771. cmDspSetDefaultUInt( ctx, &p->inst, kIndexSfId, 0, 0);
  772. cmDspSetDefaultUInt( ctx, &p->inst, kOutSfId, 0, 0);
  773. cmDspSetDefaultDouble( ctx, &p->inst, kDynSfId, 0, 0);
  774. cmDspSetDefaultDouble( ctx, &p->inst, kEvenSfId, 0, 0);
  775. cmDspSetDefaultDouble( ctx, &p->inst, kTempoSfId, 0, 0);
  776. cmDspSetDefaultDouble( ctx, &p->inst, kCostSfId, 0, 0);
  777. cmDspSetDefaultSymbol(ctx,&p->inst, kCmdSfId, p->quietSymId );
  778. return &p->inst;
  779. }
  780. cmDspRC_t _cmDspScFolFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  781. {
  782. cmDspScFol_t* p = (cmDspScFol_t*)inst;
  783. cmScMatcherFree(&p->sfp);
  784. cmScMeasFree(&p->smp);
  785. cmScoreFinalize(&p->scH);
  786. return kOkDspRC;
  787. }
  788. // This is a callback function from cmScMatcherExec() which is called when
  789. // this cmDspFol object receives a new score location index.
  790. void _cmScFolMatcherCb( cmScMatcher* p, void* arg, cmScMatcherResult_t* rp )
  791. {
  792. cmDspScFolCbArg_t* ap = (cmDspScFolCbArg_t*)arg;
  793. if( cmScMeasExec(ap->sfp->smp, rp->mni, rp->locIdx, rp->scEvtIdx, rp->flags, rp->smpIdx, rp->pitch, rp->vel ) == cmOkRC )
  794. {
  795. cmDspInst_t* inst = &(ap->sfp->inst);
  796. // send 'set' values that were calculated on the previous call to cmScMeasExec()
  797. unsigned i;
  798. for(i=ap->sfp->smp->vsi; i<ap->sfp->smp->nsi; ++i)
  799. if(ap->sfp->smp->set[i].value != DBL_MAX )
  800. {
  801. switch( ap->sfp->smp->set[i].sp->varId )
  802. {
  803. case kEvenVarScId:
  804. cmDspSetDouble(ap->ctx,inst,kEvenSfId,ap->sfp->smp->set[i].value);
  805. break;
  806. case kDynVarScId:
  807. cmDspSetDouble(ap->ctx,inst,kDynSfId,ap->sfp->smp->set[i].value);
  808. break;
  809. case kTempoVarScId:
  810. cmDspSetDouble(ap->ctx,inst,kTempoSfId,ap->sfp->smp->set[i].value);
  811. break;
  812. default:
  813. { assert(0); }
  814. }
  815. cmDspSetDouble(ap->ctx,inst,kCostSfId,ap->sfp->smp->set[i].match_cost);
  816. // Set the values in the global variable storage
  817. cmDspValue_t vv,cv;
  818. unsigned j;
  819. cmDsvSetDouble(&vv,ap->sfp->smp->set[i].value);
  820. cmDsvSetDouble(&cv,ap->sfp->smp->set[i].match_cost);
  821. for(j=0; j<ap->sfp->smp->set[i].sp->sectCnt; ++j)
  822. {
  823. cmDspStoreSetValueViaSym(ap->ctx->dsH, ap->sfp->smp->set[i].sp->symArray[j], &vv );
  824. cmDspStoreSetValueViaSym(ap->ctx->dsH, ap->sfp->smp->set[i].sp->costSymArray[j], &cv );
  825. cmDspSetSymbol(ap->ctx,inst,kSymSfId,ap->sfp->smp->set[i].sp->symArray[j]);
  826. cmDspSetSymbol(ap->ctx,inst,kSymSfId,ap->sfp->smp->set[i].sp->costSymArray[j]);
  827. }
  828. }
  829. /*
  830. // trigger 'section' starts
  831. for(i=ap->sfp->smp->vsli; i<ap->sfp->smp->nsli; ++i)
  832. {
  833. const cmScoreLoc_t* locPtr = cmScoreLoc(ap->sfp->smp->mp->scH,i);
  834. if( locPtr->begSectPtr != NULL )
  835. cmDspSetUInt(ap->ctx,inst,kSectIndexSfId,locPtr->begSectPtr->index);
  836. }
  837. */
  838. }
  839. }
  840. cmDspRC_t _cmDspScFolOpenScore( cmDspCtx_t* ctx, cmDspInst_t* inst )
  841. {
  842. cmDspRC_t rc = kOkDspRC;
  843. cmDspScFol_t* p = (cmDspScFol_t*)inst;
  844. const cmChar_t* fn;
  845. if((fn = cmDspStrcz(inst,kFnSfId)) == NULL || strlen(fn)==0 )
  846. return cmErrMsg(&inst->classPtr->err, kInvalidArgDspRC, "No score file name supplied.");
  847. if( cmScoreInitialize(ctx->cmCtx, &p->scH, fn, cmDspSampleRate(ctx), NULL, 0, NULL, NULL, ctx->stH ) != kOkScRC )
  848. return cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Unable to open the score '%s'.",fn);
  849. if( cmScoreIsValid(p->scH) )
  850. {
  851. unsigned* dynRefArray = NULL;
  852. unsigned dynRefCnt = 0;
  853. // initialize the cmScMatcher
  854. if( cmScMatcherInit(p->sfp, cmDspSampleRate(ctx), p->scH, cmDspUInt(inst,kMaxWndCntSfId), cmDspUInt(inst,kBufCntSfId), _cmScFolMatcherCb, p->smp ) != cmOkRC )
  855. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Internal score follower allocation failed.");
  856. // read the dynamics reference array
  857. if( cmDspRsrcUIntArray(ctx->dspH, &dynRefCnt, &dynRefArray, "dynRef", NULL ) != kOkDspRC )
  858. {
  859. rc = cmErrMsg(&inst->classPtr->err, kRsrcNotFoundDspRC, "The dynamics reference array resource was not found.");
  860. goto errLabel;
  861. }
  862. // initialize the cmScMeas object.
  863. if( cmScMeasInit(p->smp, p->scH, cmDspSampleRate(ctx), dynRefArray, dynRefCnt ) != cmOkRC )
  864. rc = cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Internal scMeas object initialization failed.");
  865. }
  866. errLabel:
  867. return rc;
  868. }
  869. cmDspRC_t _cmDspScFolReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  870. {
  871. cmDspRC_t rc;
  872. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  873. return rc;
  874. return _cmDspScFolOpenScore(ctx,inst);
  875. }
  876. cmDspRC_t _cmDspScFolRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  877. {
  878. cmDspRC_t rc = kOkDspRC;
  879. cmDspScFol_t* p = (cmDspScFol_t*)inst;
  880. if((rc = cmDspSetEvent(ctx,inst,evt)) == kOkDspRC && p->sfp != NULL )
  881. {
  882. switch( evt->dstVarId )
  883. {
  884. case kIndexSfId:
  885. if( cmScoreIsValid(p->scH) )
  886. {
  887. if( cmScMeasReset( p->smp ) != cmOkRC )
  888. cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Score measure unit reset to score index '%i' failed.");
  889. if( cmScMatcherReset( p->sfp, cmDspUInt(inst,kIndexSfId) ) != cmOkRC )
  890. cmErrMsg(&inst->classPtr->err, kSubSysFailDspRC, "Score follower reset to score index '%i' failed.");
  891. }
  892. break;
  893. case kStatusSfId:
  894. if( cmScoreIsValid(p->scH))
  895. {
  896. unsigned scLocIdx = cmInvalidIdx;
  897. // setup the cmScMeas() callback arg.
  898. p->arg.ctx = ctx;
  899. p->arg.sfp = p;
  900. p->sfp->cbArg = &p->arg;
  901. // this call may result in a callback to _cmScFolMatcherCb()
  902. if( cmScMatcherExec(p->sfp, cmDspUInt(inst,kSmpIdxSfId), cmDspUInt(inst,kStatusSfId), cmDspUInt(inst,kD0SfId), cmDspUInt(inst,kD1SfId), &scLocIdx) == cmOkRC )
  903. if( scLocIdx != cmInvalidIdx )
  904. cmDspSetUInt(ctx,inst,kOutSfId,scLocIdx);
  905. }
  906. break;
  907. case kFnSfId:
  908. _cmDspScFolOpenScore(ctx,inst);
  909. break;
  910. case kCmdSfId:
  911. if( cmDspSymbol(inst,kCmdSfId) == p->printSymId )
  912. p->sfp->printFl = true;
  913. else
  914. if( cmDspSymbol(inst,kCmdSfId) == p->quietSymId )
  915. p->sfp->printFl = false;
  916. break;
  917. }
  918. }
  919. return rc;
  920. }
  921. struct cmDspClass_str* cmScFolClassCons( cmDspCtx_t* ctx )
  922. {
  923. cmDspClassSetup(&_cmScFolDC,ctx,"ScFol",
  924. NULL,
  925. _cmDspScFolAlloc,
  926. _cmDspScFolFree,
  927. _cmDspScFolReset,
  928. NULL,
  929. _cmDspScFolRecv,
  930. NULL,NULL,
  931. "Score Follower");
  932. return &_cmScFolDC;
  933. }
  934. //==========================================================================================================================================
  935. enum
  936. {
  937. kScLocIdxMdId,
  938. kResetIdxMdId,
  939. kCmdMdId,
  940. kPostMdId
  941. };
  942. cmDspClass_t _cmModulatorDC;
  943. typedef struct
  944. {
  945. cmDspInst_t inst;
  946. cmScModulator* mp;
  947. cmDspCtx_t* tmp_ctx; // used to temporarily hold the current cmDspCtx during callback
  948. cmChar_t* fn;
  949. cmChar_t* modLabel;
  950. unsigned onSymId;
  951. unsigned offSymId;
  952. unsigned postSymId;
  953. } cmDspScMod_t;
  954. void _cmDspScModCb( void* arg, unsigned varSymId, double value, bool postFl )
  955. {
  956. cmDspScMod_t* p = (cmDspScMod_t*)arg;
  957. cmDspVar_t* varPtr;
  958. if((varPtr = cmDspVarSymbolToPtr( p->tmp_ctx, &p->inst, varSymId, 0 )) == NULL )
  959. return;
  960. cmDspSetDouble(p->tmp_ctx,&p->inst,varPtr->constId,value);
  961. if( postFl )
  962. cmDspSetSymbol(p->tmp_ctx,&p->inst,kPostMdId,p->postSymId);
  963. }
  964. cmDspInst_t* _cmDspScModAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  965. {
  966. va_list vl1;
  967. va_copy(vl1,vl);
  968. cmDspVarArg_t args[] =
  969. {
  970. { "index", kScLocIdxMdId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower index input."},
  971. { "reset", kResetIdxMdId, 0,0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reset the modulator and go to the score index."},
  972. { "cmd", kCmdMdId, 0,0, kInDsvFl | kSymDsvFl | kOptArgDsvFl, "on | off."},
  973. { "post", kPostMdId, 0,0, kOutDsvFl | kSymDsvFl, "Sends 'post' symbol after a message transmission if the 'post' flag is set in scMod."},
  974. { NULL, 0, 0, 0, 0 }
  975. };
  976. // validate the argument count
  977. if( va_cnt != 2 )
  978. {
  979. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The Modulator requires at least two arguments.");
  980. return NULL;
  981. }
  982. // read the modulator file and label strings
  983. const cmChar_t* fn = va_arg(vl1,const cmChar_t*);
  984. const cmChar_t* modLabel = va_arg(vl1,const cmChar_t*);
  985. va_end(vl1);
  986. // validate the file
  987. if( fn==NULL || cmFsIsFile(fn)==false )
  988. {
  989. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The Modulator file '%s' is not valid.",cmStringNullGuard(fn));
  990. return NULL;
  991. }
  992. // allocate the internal modulator object
  993. cmScModulator* mp = cmScModulatorAlloc(ctx->cmProcCtx, NULL, ctx->cmCtx, ctx->stH, cmDspSampleRate(ctx), cmDspSamplesPerCycle(ctx), fn, modLabel, _cmDspScModCb, NULL );
  994. if(mp == NULL )
  995. {
  996. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The internal modulator object initialization failed.");
  997. return NULL;
  998. }
  999. unsigned fixArgCnt = sizeof(args)/sizeof(args[0]) - 1;
  1000. unsigned argCnt = fixArgCnt + cmScModulatorOutVarCount(mp);
  1001. cmDspVarArg_t a[ argCnt+1 ];
  1002. unsigned i;
  1003. cmDspArgCopy( a, argCnt, 0, args, fixArgCnt );
  1004. for(i=fixArgCnt; i<argCnt; ++i)
  1005. {
  1006. unsigned varIdx = i - fixArgCnt;
  1007. const cmScModVar_t* vp = cmScModulatorOutVar(mp,varIdx);
  1008. const cmChar_t* label = cmSymTblLabel( ctx->stH, vp->varSymId );
  1009. const cmChar_t* docStr = cmTsPrintfS("Variable output for %s",label);
  1010. cmDspArgSetup(ctx, a + i, label, cmInvalidId, i, 0, 0, kOutDsvFl | kDoubleDsvFl, docStr );
  1011. }
  1012. cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
  1013. cmDspScMod_t* p = cmDspInstAlloc(cmDspScMod_t,ctx,classPtr,a,instSymId,id,storeSymId,va_cnt,vl);
  1014. p->fn = cmMemAllocStr(fn);
  1015. p->modLabel = cmMemAllocStr(modLabel);
  1016. p->mp = mp;
  1017. p->onSymId = cmSymTblId(ctx->stH,"on");
  1018. p->offSymId = cmSymTblId(ctx->stH,"off");
  1019. p->postSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"post");
  1020. mp->cbArg = p; // set the modulator callback arg
  1021. cmDspSetDefaultUInt(ctx,&p->inst,kScLocIdxMdId,0,0);
  1022. cmDspSetDefaultSymbol(ctx,&p->inst,kCmdMdId,p->offSymId);
  1023. return &p->inst;
  1024. }
  1025. cmDspRC_t _cmDspScModFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1026. {
  1027. cmDspRC_t rc = kOkDspRC;
  1028. cmDspScMod_t* p = (cmDspScMod_t*)inst;
  1029. if( cmScModulatorFree(&p->mp) != kOkTlRC )
  1030. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Modulator release failed.");
  1031. cmMemFree(p->fn);
  1032. cmMemFree(p->modLabel);
  1033. return rc;
  1034. }
  1035. cmDspRC_t _cmDspScModReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1036. {
  1037. cmDspRC_t rc = kOkDspRC;
  1038. cmDspApplyAllDefaults(ctx,inst);
  1039. return rc;
  1040. }
  1041. cmDspRC_t _cmDspScModRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1042. {
  1043. cmDspScMod_t* p = (cmDspScMod_t*)inst;
  1044. cmDspSetEvent(ctx,inst,evt);
  1045. switch( evt->dstVarId )
  1046. {
  1047. case kResetIdxMdId:
  1048. cmDspSetUInt(ctx,inst,kScLocIdxMdId,cmDspUInt(inst,kResetIdxMdId));
  1049. break;
  1050. case kCmdMdId:
  1051. {
  1052. unsigned symId = cmDspSymbol(inst,kCmdMdId);
  1053. if( symId == p->onSymId )
  1054. cmScModulatorReset(p->mp, ctx->cmCtx, cmDspUInt(inst,kScLocIdxMdId));
  1055. }
  1056. break;
  1057. }
  1058. return kOkDspRC;
  1059. }
  1060. cmDspRC_t _cmDspScModExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1061. {
  1062. cmDspRC_t rc = kOkDspRC;
  1063. cmDspScMod_t* p = (cmDspScMod_t*)inst;
  1064. if( cmDspSymbol(inst,kCmdMdId) != p->offSymId )
  1065. {
  1066. p->tmp_ctx = ctx;
  1067. cmScModulatorExec(p->mp,cmDspUInt(inst,kScLocIdxMdId));
  1068. }
  1069. return rc;
  1070. }
  1071. struct cmDspClass_str* cmScModClassCons( cmDspCtx_t* ctx )
  1072. {
  1073. cmDspClassSetup(&_cmModulatorDC,ctx,"ScMod",
  1074. NULL,
  1075. _cmDspScModAlloc,
  1076. _cmDspScModFree,
  1077. _cmDspScModReset,
  1078. _cmDspScModExec,
  1079. _cmDspScModRecv,
  1080. NULL,NULL,
  1081. "Score Driven Variable Modulator.");
  1082. return &_cmModulatorDC;
  1083. }
  1084. //==========================================================================================================================================
  1085. enum
  1086. {
  1087. kInChCntGsId,
  1088. kOutGroupCntGsId,
  1089. kGroupSelIdxGsId,
  1090. kBaseInFloatGsId
  1091. };
  1092. cmDspClass_t _cmGSwitchDC;
  1093. typedef struct
  1094. {
  1095. cmDspInst_t inst;
  1096. unsigned iChCnt;
  1097. unsigned oGroupCnt;
  1098. unsigned baseInFloatGsId;
  1099. unsigned baseInSymGsId;
  1100. unsigned baseInBoolGsId;
  1101. unsigned baseOutFloatGsId;
  1102. unsigned baseOutSymGsId;
  1103. unsigned baseOutBoolGsId;
  1104. } cmDspGSwitch_t;
  1105. cmDspInst_t* _cmDspGSwitchAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1106. {
  1107. va_list vl1;
  1108. va_copy(vl1,vl);
  1109. cmDspVarArg_t args[] =
  1110. {
  1111. { "ichs", kInChCntGsId, 0,0, kUIntDsvFl | kReqArgDsvFl, "Input channel count."},
  1112. { "ochs", kOutGroupCntGsId, 0,0, kUIntDsvFl | kReqArgDsvFl, "Output group count."},
  1113. { "sel", kGroupSelIdxGsId, 0,0, kInDsvFl | kUIntDsvFl, "Group select index."},
  1114. { NULL, 0, 0, 0, 0 }
  1115. };
  1116. // validate the argument count
  1117. if( va_cnt != 2 )
  1118. {
  1119. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The GSwitch requires at least two arguments.");
  1120. return NULL;
  1121. }
  1122. // read the input ch and output group count
  1123. unsigned iChCnt = va_arg(vl1,unsigned);
  1124. unsigned oGroupCnt = va_arg(vl1,unsigned);
  1125. va_end(vl1);
  1126. // validate the channel counts
  1127. if( iChCnt == 0 || oGroupCnt==0 )
  1128. {
  1129. cmDspClassErr(ctx,classPtr,kInvalidArgDspRC,"The GSwitch input channel count and group count must be greater than zero.");
  1130. return NULL;
  1131. }
  1132. unsigned typeCnt = 3; // i.e. float,sym,bool
  1133. unsigned baseInFloatGsId = kBaseInFloatGsId;
  1134. unsigned baseInSymGsId = baseInFloatGsId + iChCnt;
  1135. unsigned baseInBoolGsId = baseInSymGsId + iChCnt;
  1136. unsigned baseOutFloatGsId = baseInBoolGsId + iChCnt;
  1137. unsigned baseOutSymGsId = baseOutFloatGsId + (iChCnt * oGroupCnt);
  1138. unsigned baseOutBoolGsId = baseOutSymGsId + (iChCnt * oGroupCnt);
  1139. unsigned fixArgCnt = 3;
  1140. unsigned varArgCnt = (iChCnt * typeCnt) + (iChCnt * typeCnt * oGroupCnt);
  1141. unsigned argCnt = fixArgCnt + varArgCnt;
  1142. cmDspVarArg_t a[ argCnt+1 ];
  1143. unsigned i;
  1144. cmDspArgCopy( a, argCnt, 0, args, fixArgCnt );
  1145. cmDspArgSetupN( ctx, a, argCnt, baseInFloatGsId, iChCnt, "f-in", baseInFloatGsId, 0, 0, kInDsvFl | kDoubleDsvFl, "Float input");
  1146. cmDspArgSetupN( ctx, a, argCnt, baseInSymGsId, iChCnt, "s-in", baseInSymGsId, 0, 0, kInDsvFl | kSymDsvFl, "Symbol input");
  1147. cmDspArgSetupN( ctx, a, argCnt, baseInBoolGsId, iChCnt, "b-in", baseInBoolGsId, 0, 0, kInDsvFl | kBoolDsvFl, "Bool input");
  1148. unsigned labelCharCnt = 63;
  1149. cmChar_t label[labelCharCnt+1];
  1150. label[labelCharCnt] = 0;
  1151. unsigned gsid = baseOutFloatGsId;
  1152. for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
  1153. {
  1154. snprintf(label,labelCharCnt,"f-out-%i",i);
  1155. cmDspArgSetupN( ctx, a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kDoubleDsvFl, "Float output");
  1156. }
  1157. gsid = baseOutSymGsId;
  1158. for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
  1159. {
  1160. snprintf(label,labelCharCnt,"s-out-%i",i);
  1161. cmDspArgSetupN( ctx, a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kSymDsvFl, "Symbol output");
  1162. }
  1163. gsid = baseOutBoolGsId;
  1164. for(i=0; i<oGroupCnt; ++i, gsid+=iChCnt)
  1165. {
  1166. snprintf(label,labelCharCnt,"b-out-%i",i);
  1167. cmDspArgSetupN( ctx,a, argCnt, gsid, iChCnt, label, gsid, 0, 0, kInDsvFl | kBoolDsvFl, "Bool output");
  1168. }
  1169. cmDspArgSetupNull(a+argCnt); // set terminating arg. flags
  1170. cmDspGSwitch_t* p = cmDspInstAlloc(cmDspGSwitch_t,ctx,classPtr,a,instSymId,id,storeSymId,va_cnt,vl);
  1171. p->iChCnt = iChCnt;
  1172. p->oGroupCnt = oGroupCnt;
  1173. p->baseInFloatGsId = baseInFloatGsId;
  1174. p->baseInSymGsId = baseInSymGsId;
  1175. p->baseInBoolGsId = baseInBoolGsId;
  1176. p->baseOutFloatGsId = baseOutFloatGsId;
  1177. p->baseOutSymGsId = baseOutSymGsId;
  1178. p->baseOutBoolGsId = baseOutBoolGsId;
  1179. cmDspSetDefaultUInt(ctx,&p->inst,kGroupSelIdxGsId,0,0);
  1180. return &p->inst;
  1181. }
  1182. cmDspRC_t _cmDspGSwitchReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1183. {
  1184. cmDspRC_t rc = kOkDspRC;
  1185. cmDspApplyAllDefaults(ctx,inst);
  1186. return rc;
  1187. }
  1188. cmDspRC_t _cmDspGSwitchRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1189. {
  1190. cmDspRC_t rc = kOkDspRC;
  1191. cmDspGSwitch_t* p = (cmDspGSwitch_t*)inst;
  1192. // if this is the group selector
  1193. if( evt->dstVarId == kGroupSelIdxGsId )
  1194. {
  1195. unsigned idx;
  1196. if( (idx = cmDsvGetUInt(evt->valuePtr)) > p->oGroupCnt )
  1197. cmDspInstErr(ctx,inst,kInvalidArgDspRC,"The GSwitch group select index %i is out of range %i.",idx,p->oGroupCnt);
  1198. else
  1199. cmDspSetEvent(ctx,inst,evt);
  1200. return rc;
  1201. }
  1202. // get the group selector
  1203. unsigned groupIdx = cmDspUInt(inst,kGroupSelIdxGsId);
  1204. assert( groupIdx < p->oGroupCnt);
  1205. // if this is a float input
  1206. if( p->baseInFloatGsId <= evt->dstVarId && evt->dstVarId < p->baseInFloatGsId + p->iChCnt )
  1207. {
  1208. unsigned outVarId = p->baseOutFloatGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInFloatGsId);
  1209. cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
  1210. return rc;
  1211. }
  1212. // if this is a symbol input
  1213. if( p->baseInSymGsId <= evt->dstVarId && evt->dstVarId < p->baseInSymGsId + p->iChCnt )
  1214. {
  1215. unsigned outVarId = p->baseOutSymGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInSymGsId);
  1216. cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
  1217. return rc;
  1218. }
  1219. // if this is a bool input
  1220. if( p->baseInBoolGsId <= evt->dstVarId && evt->dstVarId < p->baseInBoolGsId + p->iChCnt )
  1221. {
  1222. unsigned outVarId = p->baseOutBoolGsId + (groupIdx * p->iChCnt) + (evt->dstVarId - p->baseInBoolGsId);
  1223. cmDspValueSet(ctx, inst, outVarId, evt->valuePtr, 0 );
  1224. return rc;
  1225. }
  1226. return rc;
  1227. }
  1228. struct cmDspClass_str* cmGSwitchClassCons( cmDspCtx_t* ctx )
  1229. {
  1230. cmDspClassSetup(&_cmGSwitchDC,ctx,"GSwitch",
  1231. NULL,
  1232. _cmDspGSwitchAlloc,
  1233. NULL,
  1234. _cmDspGSwitchReset,
  1235. NULL,
  1236. _cmDspGSwitchRecv,
  1237. NULL,NULL,
  1238. "Ganged switch.");
  1239. return &_cmGSwitchDC;
  1240. }
  1241. //==========================================================================================================================================
  1242. enum
  1243. {
  1244. kMinInSrId,
  1245. kMaxInSrId,
  1246. kMinOutSrId,
  1247. kMaxOutSrId,
  1248. kValInSrId,
  1249. kValOutSrId,
  1250. };
  1251. cmDspClass_t _cmScaleRangeDC;
  1252. typedef struct
  1253. {
  1254. cmDspInst_t inst;
  1255. } cmDspScaleRange_t;
  1256. cmDspInst_t* _cmDspScaleRangeAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1257. {
  1258. va_list vl1;
  1259. va_copy(vl1,vl);
  1260. cmDspVarArg_t args[] =
  1261. {
  1262. { "min_in", kMinInSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Min Input value."},
  1263. { "max_in", kMaxInSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Min Input value."},
  1264. { "min_out", kMinOutSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Min Input value."},
  1265. { "max_out", kMaxOutSrId, 0,0, kInDsvFl | kDoubleDsvFl , "Min Input value."},
  1266. { "val_in", kValInSrId, 0,0, kInDsvFl | kDoubleDsvFl, "Input value."},
  1267. { "val_out", kValOutSrId, 0,0, kOutDsvFl | kDoubleDsvFl, "Output value"},
  1268. { NULL, 0, 0, 0, 0 }
  1269. };
  1270. cmDspScaleRange_t* p = cmDspInstAlloc(cmDspScaleRange_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  1271. cmDspSetDefaultDouble(ctx,&p->inst,kMinInSrId,0,0);
  1272. cmDspSetDefaultDouble(ctx,&p->inst,kMaxInSrId,0,1.0);
  1273. cmDspSetDefaultDouble(ctx,&p->inst,kMinOutSrId,0,0);
  1274. cmDspSetDefaultDouble(ctx,&p->inst,kMaxOutSrId,0,1.0);
  1275. return &p->inst;
  1276. }
  1277. cmDspRC_t _cmDspScaleRangeReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1278. {
  1279. cmDspRC_t rc = kOkDspRC;
  1280. cmDspApplyAllDefaults(ctx,inst);
  1281. return rc;
  1282. }
  1283. cmDspRC_t _cmDspScaleRangeRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1284. {
  1285. cmDspRC_t rc = kOkDspRC;
  1286. //cmDspScaleRange_t* p = (cmDspScaleRange_t*)inst;
  1287. cmDspSetEvent(ctx,inst,evt);
  1288. if( evt->dstVarId == kValInSrId )
  1289. {
  1290. double val = cmDspDouble(inst,kValInSrId);
  1291. double min_in = cmDspDouble(inst,kMinInSrId);
  1292. double max_in = cmDspDouble(inst,kMaxInSrId);
  1293. double min_out = cmDspDouble(inst,kMinOutSrId);
  1294. double max_out = cmDspDouble(inst,kMaxOutSrId);
  1295. double x = cmMax(min_in,cmMin(max_in,val));
  1296. x = (x - min_in)/(max_in - min_in);
  1297. x = min_out + x * (max_out - min_out);
  1298. cmDspSetDouble(ctx,inst,kValOutSrId, x );
  1299. //printf("%f (%f %f) : (%f %f) %f\n",val,min_in,max_in,min_out,max_out,x);
  1300. }
  1301. return rc;
  1302. }
  1303. struct cmDspClass_str* cmScaleRangeClassCons( cmDspCtx_t* ctx )
  1304. {
  1305. cmDspClassSetup(&_cmScaleRangeDC,ctx,"ScaleRange",
  1306. NULL,
  1307. _cmDspScaleRangeAlloc,
  1308. NULL,
  1309. _cmDspScaleRangeReset,
  1310. NULL,
  1311. _cmDspScaleRangeRecv,
  1312. NULL,NULL,
  1313. "Scale a value inside an input range to a value in the output range.");
  1314. return &_cmScaleRangeDC;
  1315. }
  1316. //==========================================================================================================================================
  1317. enum
  1318. {
  1319. kCntAmId,
  1320. kSflocAmId,
  1321. kLocAmId,
  1322. kTypeAmId,
  1323. kValueAmId,
  1324. kCstAmId,
  1325. kCmdAmId,
  1326. kScLocAmId,
  1327. kEvenAmId,
  1328. kDynAmId,
  1329. kTempoAmId,
  1330. kCostAmId
  1331. };
  1332. cmDspClass_t _cmActiveMeasDC;
  1333. typedef struct
  1334. {
  1335. unsigned loc;
  1336. unsigned type;
  1337. double value;
  1338. double cost;
  1339. } cmDspActiveMeasRecd_t;
  1340. int cmDspActiveMeasRecdCompare(const void * p0, const void * p1)
  1341. {
  1342. return ((int)((cmDspActiveMeasRecd_t*)p0)->loc) - (int)(((cmDspActiveMeasRecd_t*)p1)->loc);
  1343. }
  1344. typedef struct
  1345. {
  1346. cmDspInst_t inst;
  1347. unsigned addSymId;
  1348. unsigned clearSymId;
  1349. unsigned printSymId;
  1350. unsigned rewindSymId;
  1351. cmDspActiveMeasRecd_t* array; // array[cnt]
  1352. unsigned cnt;
  1353. unsigned nextEmptyIdx;
  1354. unsigned nextFullIdx;
  1355. } cmDspActiveMeas_t;
  1356. cmDspInst_t* _cmDspActiveMeasAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1357. {
  1358. cmDspVarArg_t args[] =
  1359. {
  1360. { "cnt", kCntAmId, 0,0, kInDsvFl | kUIntDsvFl, "Maximum count of active measurements."},
  1361. { "sfloc", kSflocAmId, 0,0, kInDsvFl | kUIntDsvFl, "Score follower location input." },
  1362. { "loc", kLocAmId, 0,0, kInDsvFl | kUIntDsvFl, "Meas. location." },
  1363. { "type", kTypeAmId, 0,0, kInDsvFl | kUIntDsvFl, "Meas. Type." },
  1364. { "val", kValueAmId, 0,0, kInDsvFl | kDoubleDsvFl, "Meas. Value."},
  1365. { "cst", kCstAmId, 0,0, kInDsvFl | kDoubleDsvFl, "Meas. Cost."},
  1366. { "cmd", kCmdAmId, 0,0, kInDsvFl | kSymDsvFl, "Commands:add | clear | dump | rewind"},
  1367. { "scloc", kScLocAmId, 0,0, kOutDsvFl | kUIntDsvFl, "Score location"},
  1368. { "even", kEvenAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Even out"},
  1369. { "dyn", kDynAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Dyn out"},
  1370. { "tempo", kTempoAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Tempo out"},
  1371. { "cost", kCostAmId, 0,0, kOutDsvFl | kDoubleDsvFl, "Cost out"},
  1372. { NULL, 0, 0, 0, 0 }
  1373. };
  1374. cmDspActiveMeas_t* p = cmDspInstAlloc(cmDspActiveMeas_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  1375. p->addSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"add");
  1376. p->clearSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"clear");
  1377. p->printSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"dump");
  1378. p->rewindSymId= cmSymTblRegisterStaticSymbol(ctx->stH,"rewind");
  1379. cmDspSetDefaultUInt( ctx,&p->inst,kCntAmId, 0,100);
  1380. cmDspSetDefaultUInt( ctx,&p->inst,kScLocAmId,0,0);
  1381. cmDspSetDefaultDouble(ctx,&p->inst,kEvenAmId, 0,0);
  1382. cmDspSetDefaultDouble(ctx,&p->inst,kDynAmId, 0,0);
  1383. cmDspSetDefaultDouble(ctx,&p->inst,kTempoAmId,0,0);
  1384. cmDspSetDefaultDouble(ctx,&p->inst,kTempoAmId,0,0);
  1385. return &p->inst;
  1386. }
  1387. cmDspRC_t _cmDspActiveMeasPrint(cmDspCtx_t* ctx, cmDspActiveMeas_t* p )
  1388. {
  1389. unsigned i;
  1390. for(i=0; i<p->nextEmptyIdx; ++i)
  1391. {
  1392. const cmChar_t* label = "<null>";
  1393. switch( p->array[i].type )
  1394. {
  1395. case kEvenVarScId: label="even "; break;
  1396. case kDynVarScId: label="dyn "; break;
  1397. case kTempoVarScId: label="tempo"; break;
  1398. default:
  1399. { assert(0); }
  1400. }
  1401. cmRptPrintf(ctx->rpt,"loc:%i %s %f %f\n",p->array[i].loc,label,p->array[i].value,p->array[i].cost);
  1402. }
  1403. return kOkDspRC;
  1404. }
  1405. cmDspRC_t _cmDspActiveMeasClear(cmDspCtx_t* ctx, cmDspActiveMeas_t* p )
  1406. {
  1407. p->nextEmptyIdx = 0;
  1408. p->nextFullIdx = cmInvalidIdx;
  1409. return kOkDspRC;
  1410. }
  1411. cmDspRC_t _cmDspActiveMeasFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1412. {
  1413. cmDspActiveMeas_t* p = (cmDspActiveMeas_t*)inst;
  1414. _cmDspActiveMeasClear(ctx,p);
  1415. cmMemPtrFree(&p->array);
  1416. return kOkDspRC;
  1417. }
  1418. cmDspRC_t _cmDspActiveMeasReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1419. {
  1420. cmDspRC_t rc = kOkDspRC;
  1421. cmDspActiveMeas_t* p = (cmDspActiveMeas_t*)inst;
  1422. cmDspApplyAllDefaults(ctx,inst);
  1423. unsigned cnt = cmMax(100,cmDspUInt(inst,kCntAmId));
  1424. _cmDspActiveMeasFree(ctx,inst,evt);
  1425. p->array = cmMemAllocZ(cmDspActiveMeasRecd_t,cnt);
  1426. p->cnt = cnt;
  1427. return rc;
  1428. }
  1429. cmDspRC_t _cmDspActiveMeasRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1430. {
  1431. cmDspRC_t rc = kOkDspRC;
  1432. cmDspActiveMeas_t* p = (cmDspActiveMeas_t*)inst;
  1433. cmDspSetEvent(ctx,inst,evt);
  1434. switch( evt->dstVarId )
  1435. {
  1436. case kSflocAmId:
  1437. if( p->nextFullIdx != cmInvalidIdx )
  1438. {
  1439. // get the recv'd score location
  1440. unsigned sflocIdx = cmDspUInt(inst,kSflocAmId);
  1441. unsigned prvLoc = cmInvalidIdx;
  1442. // for each remaining avail record
  1443. for(; p->nextFullIdx < p->nextEmptyIdx; p->nextFullIdx++)
  1444. {
  1445. cmDspActiveMeasRecd_t* r = p->array + p->nextFullIdx;
  1446. // if this records score location is after the recv'd score loc then we're done
  1447. if( r->loc > sflocIdx )
  1448. break;
  1449. // deterimine the records type
  1450. unsigned varId = cmInvalidId;
  1451. switch( r->type )
  1452. {
  1453. case kEvenVarScId: varId = kEvenAmId; break;
  1454. case kDynVarScId: varId = kDynAmId; break;
  1455. case kTempoVarScId: varId = kTempoAmId; break;
  1456. default:
  1457. { assert(0); }
  1458. }
  1459. // if this score location has not yet been sent then send it now
  1460. if( prvLoc != r->loc )
  1461. cmDspSetUInt(ctx,inst,kScLocAmId,r->loc);
  1462. // transmit the records value and cost
  1463. cmDspSetDouble(ctx,inst,varId,r->value);
  1464. cmDspSetDouble(ctx,inst,kCostAmId,r->cost);
  1465. prvLoc = r->loc;
  1466. }
  1467. }
  1468. break;
  1469. case kCmdAmId:
  1470. {
  1471. unsigned cmdSymId = cmDspSymbol(inst,kCmdAmId);
  1472. if( cmdSymId == p->addSymId )
  1473. {
  1474. if( p->nextEmptyIdx >= p->cnt )
  1475. cmDspInstErr(ctx,inst,kProcFailDspRC,"The active measurement list is full cnt=%i.",p->cnt);
  1476. else
  1477. {
  1478. cmDspActiveMeasRecd_t* r = p->array + p->nextEmptyIdx;
  1479. r->loc = cmDspUInt( inst,kLocAmId);
  1480. r->type = cmDspUInt( inst,kTypeAmId);
  1481. r->value = cmDspDouble(inst,kValueAmId);
  1482. r->cost = cmDspDouble(inst,kCstAmId);
  1483. p->nextEmptyIdx += 1;
  1484. qsort(p->array,p->nextEmptyIdx,sizeof(p->array[0]),cmDspActiveMeasRecdCompare);
  1485. if( p->nextEmptyIdx == 1 && p->nextFullIdx == cmInvalidIdx )
  1486. p->nextFullIdx = 0;
  1487. }
  1488. }
  1489. if( cmdSymId == p->clearSymId )
  1490. rc = _cmDspActiveMeasClear(ctx,p);
  1491. else
  1492. if( cmdSymId == p->printSymId )
  1493. rc = _cmDspActiveMeasPrint(ctx,p);
  1494. else
  1495. if(cmdSymId == p->rewindSymId )
  1496. p->nextFullIdx = 0;
  1497. }
  1498. break;
  1499. }
  1500. return rc;
  1501. }
  1502. struct cmDspClass_str* cmActiveMeasClassCons( cmDspCtx_t* ctx )
  1503. {
  1504. cmDspClassSetup(&_cmActiveMeasDC,ctx,"ActiveMeas",
  1505. NULL,
  1506. _cmDspActiveMeasAlloc,
  1507. _cmDspActiveMeasFree,
  1508. _cmDspActiveMeasReset,
  1509. NULL,
  1510. _cmDspActiveMeasRecv,
  1511. NULL,NULL,
  1512. "Scale a value inside an input range to a value in the output range.");
  1513. return &_cmActiveMeasDC;
  1514. }
  1515. //==========================================================================================================================================
  1516. // Audio MIDI Sync
  1517. enum
  1518. {
  1519. kSelAmId,
  1520. kAFnAmId,
  1521. kASmpAmId,
  1522. kMFnAmId,
  1523. kMIdAmId,
  1524. };
  1525. enum
  1526. {
  1527. kAfnAmFl = 0x01,
  1528. kMfnAmFl = 0x02,
  1529. kAsmpAmFl = 0x04,
  1530. kMidAmFl = 0x08,
  1531. };
  1532. cmDspClass_t _cmAmSyncDC;
  1533. typedef struct cmDspAmSyncEntry_str
  1534. {
  1535. const cmChar_t* afn;
  1536. const cmChar_t* mfn;
  1537. unsigned asmp; // Audio sample index to sync to MIDI event
  1538. unsigned mid; // MIDI event unique id (cmMidiTrackMsg_t.uid)
  1539. int afi;
  1540. int mfi;
  1541. unsigned state;
  1542. } cmDspAmSyncEntry_t;
  1543. typedef struct
  1544. {
  1545. cmDspInst_t inst;
  1546. cmDspAmSyncEntry_t* array;
  1547. unsigned arrayCnt;
  1548. cmDspAmSyncEntry_t* acur;
  1549. cmDspAmSyncEntry_t* mcur;
  1550. } cmDspAmSync_t;
  1551. cmDspInst_t* _cmDspAmSyncAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1552. {
  1553. cmDspVarArg_t args[] =
  1554. {
  1555. { "sel", kSelAmId, 0, 0, kInDsvFl | kTypeDsvMask, "Print and reset" },
  1556. { "afn", kAFnAmId, 0, 0, kInDsvFl | kStrzDsvFl, "Audio File name"},
  1557. { "asmp", kASmpAmId, 0, 0, kInDsvFl | kIntDsvFl, "Audio sample index"},
  1558. { "mfn", kMFnAmId, 0, 0, kInDsvFl | kStrzDsvFl, "MIDI File name"},
  1559. { "mid", kMIdAmId, 0, 0, kInDsvFl | kIntDsvFl, "MIDI Event Unique Id"},
  1560. { NULL, 0, 0, 0, 0 }
  1561. };
  1562. cmDspAmSync_t* p = cmDspInstAlloc(cmDspAmSync_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  1563. return &p->inst;
  1564. }
  1565. cmDspRC_t _cmDspAmSyncFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1566. {
  1567. cmDspAmSync_t* p = (cmDspAmSync_t*)inst;
  1568. cmMemFree(p->array);
  1569. return kOkDspRC;
  1570. }
  1571. cmDspRC_t _cmDspAmSyncReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1572. {
  1573. cmDspRC_t rc = kOkDspRC;
  1574. cmDspAmSync_t* p = (cmDspAmSync_t*)inst;
  1575. cmDspApplyAllDefaults(ctx,inst);
  1576. cmJsonH_t jsH = cmDspSysPgmRsrcHandle(ctx->dspH);
  1577. cmJsonNode_t* np;
  1578. const cmChar_t* errLabelPtr;
  1579. unsigned i;
  1580. cmJsRC_t jsRC;
  1581. if((np = cmJsonFindValue(jsH, "amSync", NULL, kArrayTId)) == NULL )
  1582. {
  1583. rc = cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The AUDIO MIDI Sync cfg. record was not found.");
  1584. goto errLabel;
  1585. }
  1586. p->arrayCnt = cmJsonChildCount(np);
  1587. p->array = cmMemResizeZ(cmDspAmSyncEntry_t,p->array,p->arrayCnt);
  1588. for(i=0; i<p->arrayCnt; ++i)
  1589. {
  1590. cmJsonNode_t* anp = cmJsonArrayElement(np,i);
  1591. cmDspAmSyncEntry_t* r = p->array + i;
  1592. if( (jsRC = cmJsonMemberValues(anp,&errLabelPtr,
  1593. "af", kStringTId,&r->afn,
  1594. "asmp",kIntTId, &r->asmp,
  1595. "mf", kStringTId,&r->mfn,
  1596. "mid", kIntTId, &r->mid,
  1597. NULL)) != kOkJsRC )
  1598. {
  1599. if( jsRC == kNodeNotFoundJsRC )
  1600. rc = cmDspInstErr(ctx,inst,kRsrcNotFoundDspRC,"The Audio-MIDI Sync cfg. field '%s' was missing in the cfg. record at index %i.",errLabelPtr,i);
  1601. else
  1602. rc = cmDspInstErr(ctx,inst,kInvalidArgDspRC,"The AUDIO MIDI Sync cfg. parse failed on the record at index %i.",i);
  1603. break;
  1604. }
  1605. r->afi = cmInvalidIdx;
  1606. r->mfi = cmInvalidIdx;
  1607. r->state = 0;
  1608. }
  1609. errLabel:
  1610. return rc;
  1611. }
  1612. cmDspRC_t _cmDspAmSyncRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1613. {
  1614. cmDspAmSync_t* p = (cmDspAmSync_t*)inst;
  1615. unsigned i;
  1616. if( evt->dstVarId != kSelAmId )
  1617. cmDspSetEvent(ctx,inst,evt);
  1618. switch(evt->dstVarId)
  1619. {
  1620. case kSelAmId:
  1621. {
  1622. double srate = cmDspSysSampleRate(ctx->dspH);
  1623. int fpc = cmDspSamplesPerCycle(ctx);
  1624. for(i=0; i<p->arrayCnt; ++i)
  1625. {
  1626. cmDspAmSyncEntry_t* r = p->array + i;
  1627. int dframes = r->mfi-r->afi;
  1628. cmRptPrintf(ctx->rpt,"0x%x : %s %i %i - %s %i %i : frm:%i smp:%i sec:%f\n",
  1629. r->state,r->afn,r->asmp,r->afi,r->mfn,r->mid,r->mfi,dframes,dframes*fpc,dframes*fpc/srate);
  1630. r->afi = cmInvalidIdx;
  1631. r->mfi = cmInvalidIdx;
  1632. r->state = 0;
  1633. }
  1634. p->acur = NULL;
  1635. p->mcur = NULL;
  1636. }
  1637. break;
  1638. case kAFnAmId:
  1639. {
  1640. const cmChar_t* fn = cmDspStrcz(inst, kAFnAmId );
  1641. for(i=0; i<p->arrayCnt; ++i)
  1642. if( strcmp(fn,p->array[i].afn) == 0 )
  1643. {
  1644. p->array[i].state = cmSetFlag(p->array[i].state,kAfnAmFl);
  1645. p->acur = p->array + i;
  1646. }
  1647. }
  1648. break;
  1649. case kMFnAmId:
  1650. {
  1651. const cmChar_t* fn = cmDspStrcz(inst, kMFnAmId );
  1652. for(i=0; i<p->arrayCnt; ++i)
  1653. if( strcmp(fn,p->array[i].mfn) == 0 )
  1654. {
  1655. p->array[i].state = cmSetFlag(p->array[i].state,kMfnAmFl);
  1656. p->mcur = p->array + i;
  1657. }
  1658. }
  1659. break;
  1660. case kASmpAmId:
  1661. {
  1662. int v = cmDspInt(inst,kASmpAmId);
  1663. if( p->acur != NULL )
  1664. for(i=0; i<p->arrayCnt; ++i)
  1665. {
  1666. cmDspAmSyncEntry_t* r = p->array + i;
  1667. if( cmIsNotFlag(r->state,kAsmpAmFl) && r->asmp <= v && strcmp(p->acur->afn,r->afn)==0 )
  1668. {
  1669. r->afi = ctx->cycleCnt;
  1670. r->state = cmSetFlag(r->state,kAsmpAmFl);
  1671. break;
  1672. }
  1673. }
  1674. }
  1675. break;
  1676. case kMIdAmId:
  1677. {
  1678. int v = cmDspInt(inst,kMIdAmId);
  1679. if( p->mcur != NULL )
  1680. for(i=0; i<p->arrayCnt; ++i)
  1681. {
  1682. cmDspAmSyncEntry_t* r = p->array + i;
  1683. if( cmIsNotFlag(r->state,kMidAmFl) && r->mid == v && strcmp(p->mcur->mfn,r->mfn)==0 )
  1684. {
  1685. r->mfi = ctx->cycleCnt;
  1686. r->state = cmSetFlag(r->state,kMidAmFl);
  1687. break;
  1688. }
  1689. }
  1690. }
  1691. break;
  1692. }
  1693. return kOkDspRC;
  1694. }
  1695. struct cmDspClass_str* cmAmSyncClassCons( cmDspCtx_t* ctx )
  1696. {
  1697. cmDspClassSetup(&_cmAmSyncDC,ctx,"AmSync",
  1698. NULL,
  1699. _cmDspAmSyncAlloc,
  1700. _cmDspAmSyncFree,
  1701. _cmDspAmSyncReset,
  1702. NULL,
  1703. _cmDspAmSyncRecv,
  1704. NULL,NULL,
  1705. "Audio - MIDI Sync Object.");
  1706. return &_cmAmSyncDC;
  1707. }
  1708. //==========================================================================================================================================
  1709. enum
  1710. {
  1711. kPgmNmId,
  1712. kStatusNmId,
  1713. kD0NmId,
  1714. kD1NmId,
  1715. kThruNmId
  1716. };
  1717. cmDspClass_t _cmNanoMapDC;
  1718. typedef struct
  1719. {
  1720. cmDspInst_t inst;
  1721. } cmDspNanoMap_t;
  1722. cmDspRC_t _cmDspNanoMapSend( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned st, unsigned d0, unsigned d1 )
  1723. {
  1724. cmDspSetUInt(ctx,inst,kD1NmId,d1);
  1725. cmDspSetUInt(ctx,inst,kD0NmId,d0);
  1726. cmDspSetUInt(ctx,inst,kStatusNmId,st);
  1727. return kOkDspRC;
  1728. }
  1729. void _cmDspNanoMapPgm( cmDspCtx_t* ctx, cmDspInst_t* inst, unsigned pgm )
  1730. {
  1731. unsigned i;
  1732. for(i=0; i<kMidiChCnt; ++i)
  1733. {
  1734. _cmDspNanoMapSend(ctx,inst,kCtlMdId+i,121,0); // reset all controllers
  1735. _cmDspNanoMapSend(ctx,inst,kCtlMdId+i,123,0); // turn all notes off
  1736. _cmDspNanoMapSend(ctx,inst,kCtlMdId+i,0,0); // switch to bank 0
  1737. _cmDspNanoMapSend(ctx,inst,kPgmMdId+i,pgm,0); // send pgm change
  1738. cmSleepMs(15);
  1739. }
  1740. }
  1741. cmDspInst_t* _cmDspNanoMapAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  1742. {
  1743. cmDspVarArg_t args[] =
  1744. {
  1745. { "pgm", kPgmNmId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Reprogram all channels to this pgm." },
  1746. { "status", kStatusNmId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI status" },
  1747. { "d0", kD0NmId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d0" },
  1748. { "d1", kD1NmId, 0, 0, kOutDsvFl | kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "MIDI channel message d1" },
  1749. { "thru", kThruNmId, 0, 0, kInDsvFl | kBoolDsvFl | kOptArgDsvFl, "Enable pass through."},
  1750. { NULL, 0, 0, 0, 0 }
  1751. };
  1752. cmDspNanoMap_t* p = cmDspInstAlloc(cmDspNanoMap_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  1753. cmDspSetDefaultUInt(ctx,&p->inst, kPgmNmId, 0, 0 );
  1754. return &p->inst;
  1755. }
  1756. cmDspRC_t _cmDspNanoMapReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1757. {
  1758. cmDspRC_t rc = kOkDspRC;
  1759. cmDspApplyAllDefaults(ctx,inst);
  1760. _cmDspNanoMapPgm(ctx,inst,cmDspUInt(inst,kPgmNmId));
  1761. return rc;
  1762. }
  1763. cmDspRC_t _cmDspNanoMapRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  1764. {
  1765. //cmDspNanoMap_t* p = (cmDspNanoMap_t*)inst;
  1766. switch( evt->dstVarId )
  1767. {
  1768. case kPgmNmId:
  1769. cmDspSetEvent(ctx,inst,evt);
  1770. _cmDspNanoMapPgm(ctx,inst,cmDspUInt(inst,kPgmNmId));
  1771. break;
  1772. case kStatusNmId:
  1773. {
  1774. unsigned status = cmDsvGetUInt(evt->valuePtr);
  1775. if( (status & 0xf0) == kNoteOnMdId )
  1776. {
  1777. unsigned d0 = cmDspUInt(inst,kD0NmId);
  1778. unsigned ch = d0 % 8;
  1779. status = (status & 0xf0) + ch;
  1780. cmDspSetUInt(ctx,inst,kStatusNmId,status);
  1781. }
  1782. }
  1783. break;
  1784. default:
  1785. cmDspSetEvent(ctx,inst,evt);
  1786. break;
  1787. }
  1788. return kOkDspRC;
  1789. }
  1790. struct cmDspClass_str* cmNanoMapClassCons( cmDspCtx_t* ctx )
  1791. {
  1792. cmDspClassSetup(&_cmNanoMapDC,ctx,"NanoMap",
  1793. NULL,
  1794. _cmDspNanoMapAlloc,
  1795. NULL,
  1796. _cmDspNanoMapReset,
  1797. NULL,
  1798. _cmDspNanoMapRecv,
  1799. NULL,
  1800. NULL,
  1801. "Nanosynth Mapper");
  1802. return &_cmNanoMapDC;
  1803. }