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

cmDspKr.c 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  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 "cmPrefs.h"
  15. #include "cmDspValue.h"
  16. #include "cmMsgProtocol.h"
  17. #include "cmThread.h"
  18. #include "cmUdpPort.h"
  19. #include "cmUdpNet.h"
  20. #include "cmAudioSys.h"
  21. #include "cmDspCtx.h"
  22. #include "cmDspClass.h"
  23. #include "cmDspUi.h"
  24. #include "cmOp.h"
  25. #include "cmMath.h"
  26. #include "cmAudioFile.h"
  27. #include "cmFileSys.h"
  28. #include "cmProcObj.h"
  29. #include "cmProcTemplateMain.h"
  30. #include "cmProc.h"
  31. #include "cmMidi.h"
  32. #include "cmProc2.h"
  33. #include "cmVectOpsTemplateMain.h"
  34. #include "cmAudioFile.h"
  35. #include "cmMidiFile.h"
  36. #include "cmTimeLine.h"
  37. enum
  38. {
  39. kWndSmpCntKrId,
  40. kHopFactKrId,
  41. kModeKrId,
  42. kThreshKrId,
  43. kLwrSlopeKrId,
  44. kUprSlopeKrId,
  45. kOffsetKrId,
  46. kInvertKrId,
  47. kAudioInKrId,
  48. kAudioOutKrId
  49. };
  50. typedef struct
  51. {
  52. cmDspInst_t inst;
  53. cmCtx* ctx;
  54. cmSpecDist_t* sdp;
  55. } cmDspKr_t;
  56. cmDspClass_t _cmKrDC;
  57. //==========================================================================================================================================
  58. cmDspInst_t* _cmDspKrAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  59. {
  60. cmDspVarArg_t args[] =
  61. {
  62. { "wndn", kWndSmpCntKrId, 0, 0, kInDsvFl | kUIntDsvFl | kReqArgDsvFl, "Window sample count" },
  63. { "hopf", kHopFactKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Hop factor" },
  64. { "mode", kModeKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Mode 0=bypass 1=basic 2=spec cnt 3=amp env" },
  65. { "thrh", kThreshKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Threshold" },
  66. { "lwrs", kLwrSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Lower Slope"},
  67. { "uprs", kUprSlopeKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Upper Slope"},
  68. { "offs", kOffsetKrId, 0, 0, kInDsvFl | kDoubleDsvFl | kOptArgDsvFl, "Offset"},
  69. { "invt", kInvertKrId, 0, 0, kInDsvFl | kUIntDsvFl | kOptArgDsvFl, "Invert"},
  70. { "in", kAudioInKrId, 0, 0, kInDsvFl | kAudioBufDsvFl, "Audio Input" },
  71. { "out", kAudioOutKrId, 0, 1, kOutDsvFl | kAudioBufDsvFl, "Audio Output" },
  72. { NULL, 0, 0, 0, 0 }
  73. };
  74. cmDspKr_t* p = cmDspInstAlloc(cmDspKr_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  75. unsigned defWndSmpCnt = cmDspDefaultUInt(&p->inst,kWndSmpCntKrId);
  76. unsigned wndSmpCnt = cmNextPowerOfTwo( defWndSmpCnt );
  77. cmDspSetDefaultUInt( ctx,&p->inst, kWndSmpCntKrId, defWndSmpCnt, wndSmpCnt );
  78. cmDspSetDefaultUInt( ctx,&p->inst, kHopFactKrId, 0, 4 );
  79. cmDspSetDefaultUInt( ctx,&p->inst, kModeKrId, 0, kBasicModeSdId );
  80. cmDspSetDefaultDouble( ctx,&p->inst, kThreshKrId, 0, 60.0 );
  81. cmDspSetDefaultDouble( ctx,&p->inst, kLwrSlopeKrId, 0, 2.0 );
  82. cmDspSetDefaultDouble( ctx,&p->inst, kUprSlopeKrId, 0, 0.0 );
  83. cmDspSetDefaultDouble( ctx,&p->inst, kOffsetKrId, 0, 30.0);
  84. cmDspSetDefaultUInt( ctx,&p->inst, kInvertKrId, 0, 0 );
  85. //_cmDspKrCmInit(ctx,p); // initialize the cm library
  86. p->ctx = cmCtxAlloc(NULL,ctx->rpt,ctx->lhH,ctx->stH);
  87. return &p->inst;
  88. }
  89. cmDspRC_t _cmDspKrFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  90. {
  91. cmDspRC_t rc = kOkDspRC;
  92. cmDspKr_t* p = (cmDspKr_t*)inst;
  93. cmSpecDistFree(&p->sdp);
  94. cmCtxFree(&p->ctx);
  95. //_cmDspKrCmFinal(ctx,p); // finalize the cm library
  96. return rc;
  97. }
  98. cmDspRC_t _cmDspKrSetup(cmDspCtx_t* ctx, cmDspKr_t* p )
  99. {
  100. cmDspRC_t rc = kOkDspRC;
  101. unsigned wndSmpCnt = cmDspUInt(&p->inst,kWndSmpCntKrId);
  102. unsigned hopFact = cmDspUInt(&p->inst,kHopFactKrId);
  103. unsigned olaWndTypeId = kHannWndId;
  104. cmSpecDistFree(&p->sdp);
  105. p->sdp = cmSpecDistAlloc(p->ctx, NULL, cmDspSamplesPerCycle(ctx), cmDspSampleRate(ctx), wndSmpCnt, hopFact, olaWndTypeId);
  106. assert(p->sdp != NULL );
  107. if((rc = cmDspZeroAudioBuf(ctx,&p->inst,kAudioOutKrId)) != kOkDspRC )
  108. return rc;
  109. return rc;
  110. }
  111. cmDspRC_t _cmDspKrReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  112. {
  113. cmDspKr_t* p = (cmDspKr_t*)inst;
  114. cmDspRC_t rc;
  115. if((rc = cmDspApplyAllDefaults(ctx,inst)) != kOkDspRC )
  116. return rc;
  117. return _cmDspKrSetup(ctx,p);
  118. }
  119. cmDspRC_t _cmDspKrExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  120. {
  121. cmDspKr_t* p = (cmDspKr_t*)inst;
  122. cmDspRC_t rc = kOkDspRC;
  123. unsigned iChIdx = 0;
  124. const cmSample_t* ip = cmDspAudioBuf(ctx,inst,kAudioInKrId,iChIdx);
  125. unsigned iSmpCnt = cmDspVarRows(inst,kAudioInKrId);
  126. unsigned oChIdx = 0;
  127. cmSample_t* op = cmDspAudioBuf(ctx,inst,kAudioOutKrId,oChIdx);
  128. unsigned oSmpCnt = cmDspVarRows(inst,kAudioOutKrId);
  129. const cmSample_t* sp;
  130. cmSpecDistExec(p->sdp,ip,iSmpCnt);
  131. if((sp = cmSpecDistOut(p->sdp)) != NULL )
  132. vs_Copy(op,sp,oSmpCnt);
  133. return rc;
  134. }
  135. cmDspRC_t _cmDspKrRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  136. {
  137. cmDspKr_t* p = (cmDspKr_t*)inst;
  138. cmDspRC_t rc = kOkDspRC;
  139. cmDspSetEvent(ctx,inst,evt);
  140. switch( evt->dstVarId )
  141. {
  142. case kWndSmpCntKrId:
  143. case kHopFactKrId:
  144. _cmDspKrSetup(ctx,p);
  145. printf("wsn:%i hsn:%i\n",p->sdp->wndSmpCnt,p->sdp->hopSmpCnt);
  146. break;
  147. case kModeKrId:
  148. p->sdp->mode = cmDspUInt(inst,kModeKrId);
  149. printf("mode:%i\n",p->sdp->mode);
  150. break;
  151. case kThreshKrId:
  152. p->sdp->thresh = cmDspDouble(inst,kThreshKrId);
  153. break;
  154. case kUprSlopeKrId:
  155. p->sdp->uprSlope = cmDspDouble(inst,kUprSlopeKrId);
  156. printf("upr slope:%f\n",p->sdp->uprSlope);
  157. break;
  158. case kLwrSlopeKrId:
  159. p->sdp->lwrSlope = cmDspDouble(inst,kLwrSlopeKrId);
  160. printf("upr slope:%f\n",p->sdp->lwrSlope);
  161. break;
  162. case kOffsetKrId:
  163. p->sdp->offset = cmDspDouble(inst,kOffsetKrId);
  164. break;
  165. case kInvertKrId:
  166. p->sdp->invertFl = cmDspUInt(inst,kInvertKrId)!=0;
  167. break;
  168. default:
  169. { assert(0); }
  170. }
  171. return rc;
  172. }
  173. struct cmDspClass_str* cmKrClassCons( cmDspCtx_t* ctx )
  174. {
  175. cmDspClassSetup(&_cmKrDC,ctx,"Kr",
  176. NULL,
  177. _cmDspKrAlloc,
  178. _cmDspKrFree,
  179. _cmDspKrReset,
  180. _cmDspKrExec,
  181. _cmDspKrRecv,
  182. NULL,NULL,
  183. "Fourier based non-linear transformer.");
  184. return &_cmKrDC;
  185. }
  186. //==========================================================================================================================================
  187. enum
  188. {
  189. kTlFileTlId,
  190. kAudPathTlId,
  191. kSelTlId,
  192. kAudFnTlId,
  193. kMidiFnTlId,
  194. kBegSmpIdxTlId,
  195. kEndSmpIdxTlId
  196. };
  197. cmDspClass_t _cmTimeLineDC;
  198. typedef struct
  199. {
  200. cmDspInst_t inst;
  201. cmTlH_t tlH;
  202. } cmDspTimeLine_t;
  203. cmDspInst_t* _cmDspTimeLineAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  204. {
  205. cmDspVarArg_t args[] =
  206. {
  207. { "tlfile", kTlFileTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Time line file." },
  208. { "path", kAudPathTlId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "Audio path" },
  209. { "sel", kSelTlId, 0, 0, kInDsvFl | kInDsvFl | kOutDsvFl | kUIntDsvFl, "Selected marker id."},
  210. { "afn", kAudFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected Audio file." },
  211. { "mfn", kMidiFnTlId, 0, 0, kOutDsvFl | kStrzDsvFl, "Selected MIDI file." },
  212. { "bsi", kBegSmpIdxTlId, 0, 0, kOutDsvFl | kUIntDsvFl, "Begin audio sample index."},
  213. { "esi", kEndSmpIdxTlId, 0, 0, kOutDsvFl | kUIntDsvFl, "End audio sample index."},
  214. { NULL, 0, 0, 0, 0 }
  215. };
  216. cmDspTimeLine_t* p = cmDspInstAlloc(cmDspTimeLine_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  217. cmDspSetDefaultUInt( ctx, &p->inst, kSelTlId, 0, cmInvalidId);
  218. cmDspSetDefaultStrcz( ctx, &p->inst, kAudFnTlId, NULL, "");
  219. cmDspSetDefaultStrcz( ctx, &p->inst, kMidiFnTlId, NULL, "");
  220. cmDspSetDefaultUInt( ctx, &p->inst, kBegSmpIdxTlId, 0, cmInvalidIdx);
  221. cmDspSetDefaultUInt( ctx, &p->inst, kEndSmpIdxTlId, 0, cmInvalidIdx);
  222. // create the UI control
  223. cmDspUiTimeLineCreate(ctx,&p->inst,kTlFileTlId,kAudPathTlId,kSelTlId);
  224. p->tlH = cmTimeLineNullHandle;
  225. return &p->inst;
  226. }
  227. cmDspRC_t _cmDspTimeLineFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  228. {
  229. cmDspRC_t rc = kOkDspRC;
  230. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  231. if( cmTimeLineFinalize(&p->tlH) != kOkTlRC )
  232. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "Time-line finalize failed.");
  233. return rc;
  234. }
  235. cmDspRC_t _cmDspTimeLineReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  236. {
  237. cmDspRC_t rc = kOkDspRC;
  238. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  239. cmDspApplyAllDefaults(ctx,inst);
  240. const cmChar_t* tlFn;
  241. if((tlFn = cmDspStrcz(inst, kTlFileTlId )) != NULL )
  242. if( cmTimeLineInitializeFromFile(ctx->cmCtx, &p->tlH, NULL, NULL, tlFn ) != kOkTlRC )
  243. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "Time-line file open failed.");
  244. return rc;
  245. }
  246. cmDspRC_t _cmDspTimeLineRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  247. {
  248. cmDspTimeLine_t* p = (cmDspTimeLine_t*)inst;
  249. switch( evt->dstVarId )
  250. {
  251. case kSelTlId:
  252. {
  253. unsigned markerId;
  254. cmDspSetEvent(ctx,inst,evt);
  255. // get the id of the selected marker
  256. if((markerId = cmDspUInt(inst,kSelTlId)) != cmInvalidId )
  257. {
  258. // get the marker object
  259. cmTlObj_t* op;
  260. if((op = cmTimeLineIdToObj(p->tlH, cmInvalidId, markerId )) != NULL )
  261. {
  262. assert(op->typeId == kMarkerTlId);
  263. cmDspSetUInt(ctx, inst, kBegSmpIdxTlId, op->begSmpIdx );
  264. cmDspSetUInt(ctx, inst, kEndSmpIdxTlId, op->begSmpIdx + op->durSmpCnt );
  265. // locate the audio file assoc'd with the marker
  266. cmTlAudioFile_t* afp;
  267. if((afp = cmTimeLineAudioFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL)
  268. cmDspSetStrcz(ctx, inst, kAudFnTlId, afp->fn );
  269. // locate the midi file assoc'd with the marker
  270. cmTlMidiFile_t* mfp;
  271. if((mfp = cmTimeLineMidiFileAtTime(p->tlH,op->seqId,op->seqSmpIdx)) != NULL )
  272. cmDspSetStrcz(ctx, inst, kMidiFnTlId, mfp->fn );
  273. }
  274. }
  275. }
  276. break;
  277. default:
  278. {assert(0);}
  279. }
  280. return kOkDspRC;
  281. }
  282. struct cmDspClass_str* cmTimeLineClassCons( cmDspCtx_t* ctx )
  283. {
  284. cmDspClassSetup(&_cmTimeLineDC,ctx,"TimeLine",
  285. NULL,
  286. _cmDspTimeLineAlloc,
  287. _cmDspTimeLineFree,
  288. _cmDspTimeLineReset,
  289. NULL,
  290. _cmDspTimeLineRecv,
  291. NULL,NULL,
  292. "Time Line control.");
  293. return &_cmTimeLineDC;
  294. }
  295. //==========================================================================================================================================
  296. //
  297. //
  298. // Read files created by this object with the Octave function cmTextFile().
  299. //
  300. //
  301. enum
  302. {
  303. kFnMfId,
  304. kSelMfId,
  305. kBsiMfId,
  306. kEsiMfId,
  307. kStatusMfId,
  308. kD0MfId,
  309. kD1MfId
  310. };
  311. cmDspClass_t _cmMidiFilePlayDC;
  312. typedef struct
  313. {
  314. cmDspInst_t inst;
  315. cmMidiFileH_t mfH;
  316. unsigned msgIdx; // current midi file msg index
  317. unsigned bsi;
  318. unsigned esi;
  319. unsigned startSymId;
  320. unsigned stopSymId;
  321. unsigned contSymId;
  322. } cmDspMidiFilePlay_t;
  323. /*
  324. 'bsi' and 'esi' give the starting and ending sample for MIDI file playback.
  325. These indexes are relative to the start of the file.
  326. When the player recieves a 'start' msg it sets the current sample index
  327. 'si' to 'bsi' and begins scanning for the next note to play.
  328. On each call to the _cmDspMidiFilePlayExec() msgs that fall in the interval
  329. si:si+sPc-1 will be transmitted. (where sPc are the number of samples per DSP cycle).
  330. */
  331. cmDspInst_t* _cmDspMidiFilePlayAlloc(cmDspCtx_t* ctx, cmDspClass_t* classPtr, unsigned storeSymId, unsigned instSymId, unsigned id, unsigned va_cnt, va_list vl )
  332. {
  333. cmDspVarArg_t args[] =
  334. {
  335. { "fn", kFnMfId, 0, 0, kInDsvFl | kStrzDsvFl | kReqArgDsvFl, "File name"},
  336. { "sel", kSelMfId, 0, 0, kInDsvFl | kSymDsvFl, "start | stop | continue" },
  337. { "bsi", kBsiMfId, 0, 0, kInDsvFl | kUIntDsvFl, "Starting sample." },
  338. { "esi", kEsiMfId, 0, 0, kInDsvFl | kUIntDsvFl, "Ending sample."},
  339. { "status", kStatusMfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Status value output" },
  340. { "d0", kD0MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 0" },
  341. { "d1", kD1MfId, 0, 0, kOutDsvFl | kUIntDsvFl, "Data byte 1" },
  342. { NULL, 0, 0, 0, 0 }
  343. };
  344. cmDspMidiFilePlay_t* p = cmDspInstAlloc(cmDspMidiFilePlay_t,ctx,classPtr,args,instSymId,id,storeSymId,va_cnt,vl);
  345. cmDspSetDefaultUInt( ctx, &p->inst, kStatusMfId, 0, 0);
  346. cmDspSetDefaultUInt( ctx, &p->inst, kD0MfId, 0, 0);
  347. cmDspSetDefaultUInt( ctx, &p->inst, kD1MfId, 0, 0);
  348. p->startSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"start");
  349. p->stopSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"stop");
  350. p->contSymId = cmSymTblRegisterStaticSymbol(ctx->stH,"continue");
  351. p->mfH = cmMidiFileNullHandle;
  352. return &p->inst;
  353. }
  354. cmDspRC_t _cmDspMidiFilePlayFree(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  355. {
  356. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  357. if( cmMidiFileClose(&p->mfH) )
  358. return cmErrMsg(&inst->classPtr->err, kInstFinalFailDspRC, "MIDI file close failed.");
  359. return kOkDspRC;
  360. }
  361. // return the index of the msg following smpIdx
  362. unsigned _cmDspMidiFilePlaySeekMsgIdx( cmDspCtx_t* ctx, cmDspMidiFilePlay_t* p, unsigned smpIdx )
  363. {
  364. unsigned i;
  365. unsigned n = cmMidiFileMsgCount(p->mfH);
  366. const cmMidiTrackMsg_t** a = cmMidiFileMsgArray(p->mfH);
  367. double srate = cmDspSampleRate(ctx);
  368. for(i=0; i<n; ++i)
  369. if( floor(a[i]->dtick*srate) > smpIdx )
  370. break;
  371. return i==n ? cmInvalidIdx : i;
  372. }
  373. cmDspRC_t _cmDspMidiFilePlayOpen(cmDspCtx_t* ctx, cmDspInst_t* inst )
  374. {
  375. cmDspRC_t rc = kOkDspRC;
  376. const cmChar_t* fn = cmDspStrcz(inst,kFnMfId);
  377. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  378. if( cmMidiFileOpen( fn, &p->mfH, ctx->cmCtx ) != kOkFileRC )
  379. rc = cmErrMsg(&inst->classPtr->err, kInstResetFailDspRC, "MIDI file open failed.");
  380. else
  381. {
  382. p->msgIdx = 0;
  383. p->bsi = cmDspUInt(inst,kBsiMfId);
  384. p->esi = cmDspUInt(inst,kEsiMfId);
  385. cmMidiFileTickToMicros(p->mfH);
  386. }
  387. return rc;
  388. }
  389. cmDspRC_t _cmDspMidiFilePlayReset(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  390. {
  391. cmDspApplyAllDefaults(ctx,inst);
  392. return _cmDspMidiFilePlayOpen(ctx,inst);
  393. }
  394. cmDspRC_t _cmDspMidiFilePlayExec(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  395. {
  396. cmDspRC_t rc = kOkDspRC;
  397. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  398. double srate = cmDspSampleRate(ctx);
  399. unsigned sPc = cmDspSamplesPerCycle(ctx);
  400. return rc;
  401. }
  402. cmDspRC_t _cmDspMidiFilePlayRecv(cmDspCtx_t* ctx, cmDspInst_t* inst, const cmDspEvt_t* evt )
  403. {
  404. cmDspMidiFilePlay_t* p = (cmDspMidiFilePlay_t*)inst;
  405. cmDspSetEvent(ctx,inst,evt);
  406. switch(evt->dstVarId)
  407. {
  408. case kFnMfId:
  409. _cmDspMidiFilePlayOpen(ctx, inst );
  410. break;
  411. case kSelMfId:
  412. {
  413. if( cmDspSymbol(inst,kSelMfId)==p->startSymId )
  414. {
  415. _cmDspMidiFilePlaySeekMsgIdx(ctx, p, cmDspUInt(inst,kBsiMfId) );
  416. }
  417. break;
  418. }
  419. }
  420. return kOkDspRC;
  421. }
  422. struct cmDspClass_str* cmMidiFilePlayClassCons( cmDspCtx_t* ctx )
  423. {
  424. cmDspClassSetup(&_cmMidiFilePlayDC,ctx,"MidiFilePlay",
  425. NULL,
  426. _cmDspMidiFilePlayAlloc,
  427. _cmDspMidiFilePlayFree,
  428. _cmDspMidiFilePlayReset,
  429. _cmDspMidiFilePlayExec,
  430. _cmDspMidiFilePlayRecv,
  431. NULL,NULL,
  432. "Time tagged text file.");
  433. return &_cmMidiFilePlayDC;
  434. }